Skip to content

Commit 58f227b

Browse files
committed
(#204) Adjusted tests and image usage to new id property
1 parent 64b3dba commit 58f227b

8 files changed

+55
-37
lines changed

Diff for: index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {ScreenClass} from "./lib/screen.class";
77
import {LineHelper} from "./lib/util/linehelper.class";
88
import {createWindowApi} from "./lib/window.function";
99
import providerRegistry from "./lib/provider/provider-registry.class";
10+
import {loadImageResource} from "./lib/imageResources.function";
1011

1112
export {
1213
AssertClass,
@@ -49,6 +50,8 @@ const {getWindows, getActiveWindow} = createWindowApi(providerRegistry);
4950
const loadImage = providerRegistry.getImageReader().load;
5051
const saveImage = providerRegistry.getImageWriter().store;
5152

53+
const imageResource = (fileName: string) => loadImageResource(providerRegistry, screen.config.resourceDirectory, fileName);
54+
5255
export {
5356
clipboard,
5457
keyboard,
@@ -63,5 +66,6 @@ export {
6366
getWindows,
6467
getActiveWindow,
6568
loadImage,
66-
saveImage
69+
saveImage,
70+
imageResource
6771
};

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,29 @@ import { Image } from "./image.class";
22

33
describe("Image class", () => {
44
it("should return alphachannel = true for > 3 channels", () => {
5-
const SUT = new Image(200, 200, 123, 4);
5+
const SUT = new Image(200, 200, 123, 4, "id");
66
expect(SUT.hasAlphaChannel).toBeTruthy();
77
});
88

99
it("should return alphachannel = false for <= 3 channels", () => {
10-
const SUT = new Image(200, 200, 123, 3);
10+
const SUT = new Image(200, 200, 123, 3, "id");
1111
expect(SUT.hasAlphaChannel).toBeFalsy();
1212
});
1313
it("should return alphachannel = false for <= 3 channels", () => {
14-
const SUT = new Image(200, 200, 123, 2);
14+
const SUT = new Image(200, 200, 123, 2, "id");
1515
expect(SUT.hasAlphaChannel).toBeFalsy();
1616
});
1717
it("should return alphachannel = false for <= 3 channels", () => {
18-
const SUT = new Image(200, 200, 123, 1);
18+
const SUT = new Image(200, 200, 123, 1, "id");
1919
expect(SUT.hasAlphaChannel).toBeFalsy();
2020
});
2121

2222
it("should throw for <= 0 channels", () => {
23-
expect(() => new Image(200, 200, 123, 0)).toThrowError("Channel <= 0");
23+
expect(() => new Image(200, 200, 123, 0, "id")).toThrowError("Channel <= 0");
2424
});
2525

2626
it("should have a default pixel density of 1.0", () => {
27-
const SUT = new Image(200, 200, 123, 1);
27+
const SUT = new Image(200, 200, 123, 1, "id");
2828
expect(SUT.pixelDensity).toEqual({ scaleX: 1.0, scaleY: 1.0 });
2929
});
3030
});

Diff for: lib/match-request.class.spec.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ import {MatchRequest} from "./match-request.class";
44
describe("MatchRequest", () => {
55
it("should default to multi-scale matching", () => {
66
const SUT = new MatchRequest(
7-
new Image(100, 100,
8-
new ArrayBuffer(0), 3
7+
new Image(
8+
100,
9+
100,
10+
new ArrayBuffer(0),
11+
3,
12+
"haystack_image"
913
),
10-
new Image(100, 100,
11-
new ArrayBuffer(0), 3
14+
new Image(
15+
100,
16+
100,
17+
new ArrayBuffer(0),
18+
3,
19+
"needle_image"
1220
),
1321
0.99);
1422

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default class implements ImageReader {
88
Jimp.read(parameters)
99
.then(jimpImage => {
1010
// stay consistent with images retrieved from libnut which uses BGR format
11-
jimpImage.scan(0, 0, jimpImage.bitmap.width, jimpImage.bitmap.height, function(_, __, idx) {
11+
jimpImage.scan(0, 0, jimpImage.bitmap.width, jimpImage.bitmap.height, function (_, __, idx) {
1212
const red = this.bitmap.data[idx];
1313
this.bitmap.data[idx] = this.bitmap.data[idx + 2];
1414
this.bitmap.data[idx + 2] = red;
@@ -17,7 +17,8 @@ export default class implements ImageReader {
1717
jimpImage.bitmap.width,
1818
jimpImage.bitmap.height,
1919
jimpImage.bitmap.data,
20-
jimpImage.hasAlpha() ? 4 : 3
20+
jimpImage.hasAlpha() ? 4 : 3,
21+
parameters
2122
));
2223
}).catch(err => reject(`Failed to load image from '${parameters}'. Reason: ${err}`));
2324
})

Diff for: lib/provider/io/jimp-image-writer.class.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ afterEach(() => jest.resetAllMocks());
2525
describe('Jimp image writer', () => {
2626
it('should reject on writing failures', async () => {
2727
// GIVEN
28-
const outputFile = new Image(100, 200, Buffer.from([]), 3);
2928
const outputFileName = "/does/not/compute.png"
29+
const outputFile = new Image(100, 200, Buffer.from([]), 3, outputFileName);
3030
const writeMock = jest.fn(() => Promise.resolve(new Jimp()));
3131
const scanMock = jest.fn();
3232
Jimp.prototype.scan = scanMock;

Diff for: lib/provider/native/libnut-screen.class.ts

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default class ScreenAction implements ScreenProviderInterface {
3333
screenShot.height,
3434
screenShot.image,
3535
4,
36+
"grabScreenResult",
3637
pixelScaling,
3738
),
3839
);
@@ -58,6 +59,7 @@ export default class ScreenAction implements ScreenProviderInterface {
5859
screenShot.height,
5960
screenShot.image,
6061
4,
62+
"grabScreenRegionResult",
6163
pixelScaling,
6264
),
6365
);

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

+18-15
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const providerRegistryMock = mockPartial<ProviderRegistry>({
1919
getScreen(): ScreenProviderInterface {
2020
return mockPartial<ScreenProviderInterface>({
2121
grabScreenRegion(): Promise<Image> {
22-
return Promise.resolve(new Image(searchRegion.width, searchRegion.height, new ArrayBuffer(0), 3));
22+
return Promise.resolve(new Image(searchRegion.width, searchRegion.height, new ArrayBuffer(0), 3, "needle_image"));
2323
},
2424
screenSize(): Promise<Region> {
2525
return Promise.resolve(searchRegion);
@@ -38,7 +38,7 @@ describe("Screen.", () => {
3838
// GIVEN
3939
const matchResult = new MatchResult(0.99, searchRegion);
4040
const SUT = new ScreenClass(providerRegistryMock);
41-
const needle = new Image(100, 100, Buffer.from([]), 3);
41+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
4242

4343
const findMatchMock = jest.fn(() => Promise.resolve(matchResult));
4444
providerRegistryMock.getImageFinder = jest.fn(() => mockPartial<ImageFinderInterface>({
@@ -68,7 +68,7 @@ describe("Screen.", () => {
6868

6969
const SUT = new ScreenClass(providerRegistryMock);
7070
const testCallback = jest.fn(() => Promise.resolve());
71-
const needle = new Image(100, 100, Buffer.from([]), 3);
71+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
7272
SUT.on(needle, testCallback);
7373

7474
// WHEN
@@ -90,7 +90,7 @@ describe("Screen.", () => {
9090
const SUT = new ScreenClass(providerRegistryMock);
9191
const testCallback = jest.fn(() => Promise.resolve());
9292
const secondCallback = jest.fn(() => Promise.resolve());
93-
const needle = new Image(100, 100, Buffer.from([]), 3);
93+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
9494
SUT.on(needle, testCallback);
9595
SUT.on(needle, secondCallback);
9696

@@ -114,15 +114,16 @@ describe("Screen.", () => {
114114
}));
115115

116116
const SUT = new ScreenClass(providerRegistryMock);
117-
const needle = new Image(100, 100, Buffer.from([]), 3);
117+
const id = "needle_image";
118+
const needle = new Image(100, 100, Buffer.from([]), 3, id);
118119

119120
// WHEN
120121
const resultRegion = SUT.find(needle);
121122

122123
// THEN
123124
await expect(resultRegion)
124125
.rejects
125-
.toEqual(`No match for image. Required: ${SUT.config.confidence}, given: ${matchResult.confidence}`);
126+
.toEqual(`No match for ${id}. Required: ${SUT.config.confidence}, given: ${matchResult.confidence}`);
126127
});
127128

128129
it("should reject when search fails.", async () => {
@@ -135,15 +136,16 @@ describe("Screen.", () => {
135136
}));
136137

137138
const SUT = new ScreenClass(providerRegistryMock);
138-
const needle = new Image(100, 100, Buffer.from([]), 3);
139+
const id = "needle_image";
140+
const needle = new Image(100, 100, Buffer.from([]), 3, id);
139141

140142
// WHEN
141143
const resultRegion = SUT.find(needle);
142144

143145
// THEN
144146
await expect(resultRegion)
145147
.rejects
146-
.toEqual(`Searching for image failed. Reason: '${rejectionReason}'`);
148+
.toEqual(`Searching for ${id} failed. Reason: '${rejectionReason}'`);
147149
});
148150

149151
it("should override default confidence value with parameter.", async () => {
@@ -159,7 +161,7 @@ describe("Screen.", () => {
159161

160162
const SUT = new ScreenClass(providerRegistryMock);
161163

162-
const needle = new Image(100, 100, Buffer.from([]), 3);
164+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
163165
const parameters = new LocationParameters(undefined, minMatch);
164166

165167
// WHEN
@@ -187,7 +189,7 @@ describe("Screen.", () => {
187189

188190
const SUT = new ScreenClass(providerRegistryMock);
189191

190-
const needle = new Image(100, 100, Buffer.from([]), 3);
192+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
191193
const parameters = new LocationParameters(customSearchRegion);
192194
const expectedMatchRequest = new MatchRequest(
193195
expect.any(Image),
@@ -211,7 +213,7 @@ describe("Screen.", () => {
211213
}));
212214

213215
const SUT = new ScreenClass(providerRegistryMock);
214-
const needle = new Image(100, 100, Buffer.from([]), 3);
216+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
215217

216218
const parameters = new LocationParameters(searchRegion, undefined, false);
217219
const expectedMatchRequest = new MatchRequest(
@@ -238,7 +240,7 @@ describe("Screen.", () => {
238240
}));
239241

240242
const SUT = new ScreenClass(providerRegistryMock);
241-
const needle = new Image(100, 100, Buffer.from([]), 3);
243+
const needle = new Image(100, 100, Buffer.from([]), 3, "needle_image");
242244
const parameters = new LocationParameters(customSearchRegion, minMatch);
243245
const expectedMatchRequest = new MatchRequest(
244246
expect.any(Image),
@@ -273,7 +275,7 @@ describe("Screen.", () => {
273275
const SUT = new ScreenClass(providerRegistryMock);
274276
// WHEN
275277
const matchRegion = await SUT.find(
276-
new Image(100, 100, Buffer.from([]), 3),
278+
new Image(100, 100, Buffer.from([]), 3, "needle_image"),
277279
{
278280
searchRegion: limitedSearchRegion
279281
}
@@ -302,7 +304,8 @@ describe("Screen.", () => {
302304
["with NaN on height", new Region(0, 0, 100, "a" as unknown as number)],
303305
])("should reject search regions %s", async (_, region) => {
304306
// GIVEN
305-
const needle = new Image(100, 100, Buffer.from([]), 3);
307+
const id = "needle_image";
308+
const needle = new Image(100, 100, Buffer.from([]), 3, id);
306309
const matchResult = new MatchResult(0.99, region);
307310
const findMatchMock = jest.fn(() => Promise.resolve(matchResult));
308311
providerRegistryMock.getImageFinder = jest.fn(() => mockPartial<ImageFinderInterface>({
@@ -319,7 +322,7 @@ describe("Screen.", () => {
319322
});
320323

321324
// THEN
322-
await expect(findPromise).rejects.toContain(`Searching for image failed. Reason:`);
325+
await expect(findPromise).rejects.toContain(`Searching for ${id} failed. Reason:`);
323326
})
324327
});
325328

Diff for: lib/screen.class.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ export class ScreenClass {
4949
/**
5050
* {@link ScreenClass} class constructor
5151
* @param providerRegistry A {@link ProviderRegistry} used to access underlying implementations
52-
* @param findHooks A {@link Map} of {@link FindHookCallback} methods assigned to a template image filename
52+
* @param findHooks A {@link Map} of {@link FindHookCallback} methods assigned to a template image
5353
*/
5454
constructor(
5555
private providerRegistry: ProviderRegistry,
56-
private findHooks: Map<Image, FindHookCallback[]> = new Map<Image, FindHookCallback[]>()) {
56+
private findHooks: Map<string | Image, FindHookCallback[]> = new Map<string | Image, FindHookCallback[]>()) {
5757
}
5858

5959
/**
@@ -142,14 +142,14 @@ export class ScreenClass {
142142
}
143143
} else {
144144
reject(
145-
`No match for ${typeof templateImage === "string" ? templateImage : 'image'}. Required: ${minMatch}, given: ${
145+
`No match for ${needle.id}. Required: ${minMatch}, given: ${
146146
matchResult.confidence
147147
}`,
148148
);
149149
}
150150
} catch (e) {
151151
reject(
152-
`Searching for ${typeof templateImage === "string" ? templateImage : 'image'} failed. Reason: '${e}'`,
152+
`Searching for ${needle.id} failed. Reason: '${e}'`,
153153
);
154154
}
155155
});
@@ -167,24 +167,24 @@ export class ScreenClass {
167167

168168
/**
169169
* {@link waitFor} searches for a template image for a specified duration
170-
* @param templateImageFilename Filename of the template image, relative to {@link ScreenClass.config.resourceDirectory}
170+
* @param templateImage Filename of the template image, relative to {@link ScreenClass.config.resourceDirectory}, or an {@link Image}
171171
* @param timeoutMs Timeout in milliseconds after which {@link waitFor} fails
172172
* @param params {@link LocationParameters} which are used to fine tune search region and / or match confidence
173173
*/
174174
public async waitFor(
175-
templateImageFilename: string,
175+
templateImage: string | Image,
176176
timeoutMs: number = 5000,
177177
params?: LocationParameters,
178178
): Promise<Region> {
179-
return timeout(500, timeoutMs, () => this.find(templateImageFilename, params), {signal: params?.abort});
179+
return timeout(500, timeoutMs, () => this.find(templateImage, params), {signal: params?.abort});
180180
}
181181

182182
/**
183183
* {@link on} registers a callback which is triggered once a certain template image is found
184184
* @param templateImage Template image to trigger the callback on
185185
* @param callback The {@link FindHookCallback} function to trigger
186186
*/
187-
public on(templateImage: Image, callback: FindHookCallback) {
187+
public on(templateImage: string | Image, callback: FindHookCallback) {
188188
const existingHooks = this.findHooks.get(templateImage) || [];
189189
this.findHooks.set(templateImage, [...existingHooks, callback]);
190190
}

0 commit comments

Comments
 (0)