Skip to content

Commit e3df158

Browse files
committed
(#40) screen.highlight implementation and tests
1 parent 7bc68de commit e3df158

File tree

2 files changed

+354
-296
lines changed

2 files changed

+354
-296
lines changed

lib/screen.class.spec.ts

+182-152
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,217 @@
1-
import { join } from "path";
2-
import { cwd } from "process";
3-
import { VisionAdapter } from "./adapter/vision.adapter.class";
4-
import { Image } from "./image.class";
5-
import { LocationParameters } from "./locationparameters.class";
6-
import { MatchRequest } from "./match-request.class";
7-
import { MatchResult } from "./match-result.class";
8-
import { Region } from "./region.class";
9-
import { Screen } from "./screen.class";
1+
import {join} from "path";
2+
import {cwd} from "process";
3+
import {VisionAdapter} from "./adapter/vision.adapter.class";
4+
import {Image} from "./image.class";
5+
import {LocationParameters} from "./locationparameters.class";
6+
import {MatchRequest} from "./match-request.class";
7+
import {MatchResult} from "./match-result.class";
8+
import {Region} from "./region.class";
9+
import {Screen} from "./screen.class";
1010

1111
jest.mock("./adapter/native.adapter.class");
1212
jest.mock("./adapter/vision.adapter.class");
1313

1414
const searchRegion = new Region(0, 0, 100, 100);
1515

1616
beforeAll(() => {
17-
VisionAdapter.prototype.grabScreen = jest.fn(() => {
18-
return Promise.resolve(new Image(searchRegion.width, searchRegion.height, new ArrayBuffer(0), 3));
19-
});
17+
VisionAdapter.prototype.grabScreen = jest.fn(() => {
18+
return Promise.resolve(new Image(searchRegion.width, searchRegion.height, new ArrayBuffer(0), 3));
19+
});
2020

21-
VisionAdapter.prototype.screenSize = jest.fn(() => {
22-
return Promise.resolve(searchRegion);
23-
});
21+
VisionAdapter.prototype.screenSize = jest.fn(() => {
22+
return Promise.resolve(searchRegion);
23+
});
2424
});
2525

2626
describe("Screen.", () => {
27-
it("should resolve with sufficient confidence.", async () => {
28-
const matchResult = new MatchResult(0.99, searchRegion);
29-
30-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
31-
return Promise.resolve(matchResult);
27+
it("should resolve with sufficient confidence.", async () => {
28+
const matchResult = new MatchResult(0.99, searchRegion);
29+
30+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
31+
return Promise.resolve(matchResult);
32+
});
33+
34+
const visionAdapterMock = new VisionAdapter();
35+
36+
const SUT = new Screen(visionAdapterMock);
37+
const imagePath = "test/path/to/image.png";
38+
await expect(SUT.find(imagePath)).resolves.toEqual(matchResult.location);
39+
const matchRequest = new MatchRequest(
40+
expect.any(Image),
41+
join(cwd(), imagePath),
42+
searchRegion,
43+
SUT.config.confidence,
44+
true);
45+
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
3246
});
3347

34-
const visionAdapterMock = new VisionAdapter();
35-
36-
const SUT = new Screen(visionAdapterMock);
37-
const imagePath = "test/path/to/image.png";
38-
await expect(SUT.find(imagePath)).resolves.toEqual(matchResult.location);
39-
const matchRequest = new MatchRequest(
40-
expect.any(Image),
41-
join(cwd(), imagePath),
42-
searchRegion,
43-
SUT.config.confidence,
44-
true);
45-
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
46-
});
47-
48-
it("should call registered hook before resolve", async () => {
49-
const matchResult = new MatchResult(0.99, searchRegion);
50-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
51-
return Promise.resolve(matchResult);
48+
it("should call registered hook before resolve", async () => {
49+
const matchResult = new MatchResult(0.99, searchRegion);
50+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
51+
return Promise.resolve(matchResult);
52+
});
53+
const visionAdapterMock = new VisionAdapter();
54+
55+
const SUT = new Screen(visionAdapterMock);
56+
const testCallback = jest.fn(() => Promise.resolve());
57+
const imagePath = "test/path/to/image.png";
58+
SUT.on(imagePath, testCallback);
59+
await SUT.find(imagePath);
60+
expect(testCallback).toBeCalledTimes(1);
61+
expect(testCallback).toBeCalledWith(matchResult);
5262
});
53-
const visionAdapterMock = new VisionAdapter();
54-
55-
const SUT = new Screen(visionAdapterMock);
56-
const testCallback = jest.fn(() => Promise.resolve());
57-
const imagePath = "test/path/to/image.png";
58-
SUT.on(imagePath, testCallback);
59-
await SUT.find(imagePath);
60-
expect(testCallback).toBeCalledTimes(1);
61-
expect(testCallback).toBeCalledWith(matchResult);
62-
});
63-
64-
it("should call multiple registered hooks before resolve", async () => {
65-
const matchResult = new MatchResult(0.99, searchRegion);
66-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
67-
return Promise.resolve(matchResult);
63+
64+
it("should call multiple registered hooks before resolve", async () => {
65+
const matchResult = new MatchResult(0.99, searchRegion);
66+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
67+
return Promise.resolve(matchResult);
68+
});
69+
const visionAdapterMock = new VisionAdapter();
70+
71+
const SUT = new Screen(visionAdapterMock);
72+
const testCallback = jest.fn(() => Promise.resolve());
73+
const secondCallback = jest.fn(() => Promise.resolve());
74+
const imagePath = "test/path/to/image.png";
75+
SUT.on(imagePath, testCallback);
76+
SUT.on(imagePath, secondCallback);
77+
await SUT.find(imagePath);
78+
for (const callback of [testCallback, secondCallback]) {
79+
expect(callback).toBeCalledTimes(1);
80+
expect(callback).toBeCalledWith(matchResult);
81+
}
6882
});
69-
const visionAdapterMock = new VisionAdapter();
70-
71-
const SUT = new Screen(visionAdapterMock);
72-
const testCallback = jest.fn(() => Promise.resolve());
73-
const secondCallback = jest.fn(() => Promise.resolve());
74-
const imagePath = "test/path/to/image.png";
75-
SUT.on(imagePath, testCallback);
76-
SUT.on(imagePath, secondCallback);
77-
await SUT.find(imagePath);
78-
for (const callback of [testCallback, secondCallback]) {
79-
expect(callback).toBeCalledTimes(1);
80-
expect(callback).toBeCalledWith(matchResult);
81-
}
82-
});
83-
84-
it("should reject with insufficient confidence.", async () => {
85-
const matchResult = new MatchResult(0.8, searchRegion);
86-
87-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
88-
return Promise.resolve(matchResult);
83+
84+
it("should reject with insufficient confidence.", async () => {
85+
const matchResult = new MatchResult(0.8, searchRegion);
86+
87+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
88+
return Promise.resolve(matchResult);
89+
});
90+
91+
const visionAdapterMock = new VisionAdapter();
92+
93+
const SUT = new Screen(visionAdapterMock);
94+
const imagePath = "test/path/to/image.png";
95+
await expect(SUT.find(imagePath))
96+
.rejects
97+
.toEqual(`No match for ${imagePath}. Required: ${SUT.config.confidence}, given: ${matchResult.confidence}`);
8998
});
9099

91-
const visionAdapterMock = new VisionAdapter();
100+
it("should reject when search fails.", async () => {
101+
const rejectionReason = "Search failed.";
102+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
103+
return Promise.reject(rejectionReason);
104+
});
92105

93-
const SUT = new Screen(visionAdapterMock);
94-
const imagePath = "test/path/to/image.png";
95-
await expect(SUT.find(imagePath))
96-
.rejects
97-
.toEqual(`No match for ${imagePath}. Required: ${SUT.config.confidence}, given: ${matchResult.confidence}`);
98-
});
106+
const visionAdapterMock = new VisionAdapter();
99107

100-
it("should reject when search fails.", async () => {
101-
const rejectionReason = "Search failed.";
102-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
103-
return Promise.reject(rejectionReason);
108+
const SUT = new Screen(visionAdapterMock);
109+
const imagePath = "test/path/to/image.png";
110+
await expect(SUT.find(imagePath))
111+
.rejects
112+
.toEqual(`Searching for ${imagePath} failed. Reason: '${rejectionReason}'`);
104113
});
105114

106-
const visionAdapterMock = new VisionAdapter();
115+
it("should override default confidence value with parameter.", async () => {
116+
const minMatch = 0.8;
117+
const matchResult = new MatchResult(minMatch, searchRegion);
118+
119+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
120+
return Promise.resolve(matchResult);
121+
});
107122

108-
const SUT = new Screen(visionAdapterMock);
109-
const imagePath = "test/path/to/image.png";
110-
await expect(SUT.find(imagePath))
111-
.rejects
112-
.toEqual(`Searching for ${imagePath} failed. Reason: '${rejectionReason}'`);
113-
});
123+
const visionAdapterMock = new VisionAdapter();
114124

115-
it("should override default confidence value with parameter.", async () => {
116-
const minMatch = 0.8;
117-
const matchResult = new MatchResult(minMatch, searchRegion);
125+
const SUT = new Screen(visionAdapterMock);
118126

119-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
120-
return Promise.resolve(matchResult);
127+
const imagePath = "test/path/to/image.png";
128+
const parameters = new LocationParameters(undefined, minMatch);
129+
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
130+
const matchRequest = new MatchRequest(
131+
expect.any(Image),
132+
join(cwd(), imagePath),
133+
searchRegion,
134+
minMatch,
135+
true);
136+
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
121137
});
122138

123-
const visionAdapterMock = new VisionAdapter();
139+
it("should override default search region with parameter.", async () => {
140+
const customSearchRegion = new Region(10, 10, 90, 90);
141+
const matchResult = new MatchResult(0.99, searchRegion);
124142

125-
const SUT = new Screen(visionAdapterMock);
143+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
144+
return Promise.resolve(matchResult);
145+
});
126146

127-
const imagePath = "test/path/to/image.png";
128-
const parameters = new LocationParameters(undefined, minMatch);
129-
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
130-
const matchRequest = new MatchRequest(
131-
expect.any(Image),
132-
join(cwd(), imagePath),
133-
searchRegion,
134-
minMatch,
135-
true);
136-
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
137-
});
147+
const visionAdapterMock = new VisionAdapter();
138148

139-
it("should override default search region with parameter.", async () => {
140-
const customSearchRegion = new Region(10, 10, 90, 90);
141-
const matchResult = new MatchResult(0.99, searchRegion);
149+
const SUT = new Screen(visionAdapterMock);
142150

143-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
144-
return Promise.resolve(matchResult);
151+
const imagePath = "test/path/to/image.png";
152+
const parameters = new LocationParameters(customSearchRegion);
153+
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
154+
const matchRequest = new MatchRequest(
155+
expect.any(Image),
156+
join(cwd(), imagePath),
157+
customSearchRegion,
158+
SUT.config.confidence,
159+
true);
160+
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
145161
});
146162

147-
const visionAdapterMock = new VisionAdapter();
148-
149-
const SUT = new Screen(visionAdapterMock);
150-
151-
const imagePath = "test/path/to/image.png";
152-
const parameters = new LocationParameters(customSearchRegion);
153-
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
154-
const matchRequest = new MatchRequest(
155-
expect.any(Image),
156-
join(cwd(), imagePath),
157-
customSearchRegion,
158-
SUT.config.confidence,
159-
true);
160-
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
161-
});
162-
163-
it("should override both confidence and search region with parameter.", async () => {
164-
const minMatch = 0.8;
165-
const customSearchRegion = new Region(10, 10, 90, 90);
166-
const matchResult = new MatchResult(minMatch, searchRegion);
167-
168-
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
169-
return Promise.resolve(matchResult);
163+
it("should override both confidence and search region with parameter.", async () => {
164+
const minMatch = 0.8;
165+
const customSearchRegion = new Region(10, 10, 90, 90);
166+
const matchResult = new MatchResult(minMatch, searchRegion);
167+
168+
VisionAdapter.prototype.findOnScreenRegion = jest.fn(() => {
169+
return Promise.resolve(matchResult);
170+
});
171+
172+
const visionAdapterMock = new VisionAdapter();
173+
174+
const SUT = new Screen(visionAdapterMock);
175+
176+
const imagePath = "test/path/to/image.png";
177+
const parameters = new LocationParameters(customSearchRegion, minMatch);
178+
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
179+
const matchRequest = new MatchRequest(
180+
expect.any(Image),
181+
join(cwd(), imagePath),
182+
customSearchRegion,
183+
minMatch,
184+
true);
185+
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
186+
});
187+
188+
it("should return region to highlight for chaining", async () => {
189+
// GIVEN
190+
const highlightRegion = new Region(10, 20, 30, 40);
191+
VisionAdapter.prototype.highlightScreenRegion = jest.fn();
192+
const visionAdapterMock = new VisionAdapter();
193+
const SUT = new Screen(visionAdapterMock);
194+
195+
// WHEN
196+
const result = await SUT.highlight(highlightRegion);
197+
198+
// THEN
199+
expect(result).toEqual(highlightRegion);
200+
});
201+
202+
it("should handle Promises and return region to highlight for chaining", async () => {
203+
// GIVEN
204+
const highlightRegion = new Region(10, 20, 30, 40);
205+
const highlightRegionPromise = new Promise<Region>(res => res(highlightRegion));
206+
VisionAdapter.prototype.highlightScreenRegion = jest.fn();
207+
const visionAdapterMock = new VisionAdapter();
208+
const SUT = new Screen(visionAdapterMock);
209+
210+
// WHEN
211+
const result = await SUT.highlight(highlightRegionPromise);
212+
213+
// THEN
214+
expect(result).toEqual(highlightRegion);
170215
});
171216

172-
const visionAdapterMock = new VisionAdapter();
173-
174-
const SUT = new Screen(visionAdapterMock);
175-
176-
const imagePath = "test/path/to/image.png";
177-
const parameters = new LocationParameters(customSearchRegion, minMatch);
178-
await expect(SUT.find(imagePath, parameters)).resolves.toEqual(matchResult.location);
179-
const matchRequest = new MatchRequest(
180-
expect.any(Image),
181-
join(cwd(), imagePath),
182-
customSearchRegion,
183-
minMatch,
184-
true);
185-
expect(visionAdapterMock.findOnScreenRegion).toHaveBeenCalledWith(matchRequest);
186-
});
187217
});

0 commit comments

Comments
 (0)