Skip to content

Commit

Permalink
Feature/547/improve jest matchers (#549)
Browse files Browse the repository at this point in the history
* (#547) New matcher toHaveColor that verifies pixel colors on screen

* (#547) Updated toShow to support full search parameters, added the possibility to pass a region to directly specify a search region instead of the whole screen

* (#547) Expose new matchers

* (#547) npm audit fix

* (#547) Try to increase node heap space

* (#547) Try to increase node heap space

* (#547) Get rid of Docker tests

* (#547) Addressed some sonar issues

* (#547) Don't run coverage report again after the first stage
  • Loading branch information
s1hofmann committed Dec 14, 2023
1 parent 41b7b29 commit db81b6e
Show file tree
Hide file tree
Showing 19 changed files with 332 additions and 278 deletions.
26 changes: 0 additions & 26 deletions .build/build.sh

This file was deleted.

16 changes: 0 additions & 16 deletions .build/run_linux.sh

This file was deleted.

9 changes: 0 additions & 9 deletions .build/run_osx.sh

This file was deleted.

9 changes: 0 additions & 9 deletions .build/setup_linux.sh

This file was deleted.

2 changes: 0 additions & 2 deletions .build/setup_osx.sh

This file was deleted.

10 changes: 3 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 18
- name: Setup Docker
run: |
docker pull s1hofmann/nut-ci:latest
docker run -it -d --name nut-ci --shm-size 8gb --user $(id -u):$(id -g) -v ${PWD}:${PWD}:rw s1hofmann/nut-ci:latest bash
- name: Install
run: npm ci
- name: Compile
Expand All @@ -34,10 +30,10 @@ jobs:
run: npm run coverage:clean
- name: Generate coverage report
uses: GabrielBB/xvfb-action@v1
env:
NODE_OPTIONS: "--max-old-space-size=8192"
with:
run: npm run coverage -- --coverageDirectory=coverage/unit
- name: Run Docker E2E tests
run: docker exec nut-ci bash -c "bash $PWD/.build/build.sh ${PWD} 14"
- name: Run Electron e2e test subpackage
uses: GabrielBB/xvfb-action@v1
with:
Expand Down Expand Up @@ -78,7 +74,7 @@ jobs:
with:
run: |
npx playwright install --with-deps
npm run coverage -- --coverageDirectory=coverage/unit
npm test
- name: Run Electron e2e test subpackage
uses: GabrielBB/xvfb-action@v1
with:
Expand Down
8 changes: 0 additions & 8 deletions .github/workflows/snapshot_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
- name: Setup Docker
if: ${{matrix.os == 'ubuntu-latest'}}
run: |
docker pull s1hofmann/nut-ci:latest
docker run -it -d --name nut-ci --shm-size 8gb --user $(id -u):$(id -g) -v ${PWD}:${PWD}:rw s1hofmann/nut-ci:latest bash
- name: Install
run: npm ci
- name: Install @nut-tree/libnut@next
Expand All @@ -43,9 +38,6 @@ jobs:
run: |
npx playwright install --with-deps
npm test
- name: Run Docker E2E tests
if: ${{matrix.os == 'ubuntu-latest'}}
run: docker exec nut-ci bash -c "bash $PWD/.build/build.sh ${PWD} 14"
- name: Run Electron e2e test subpackage
uses: GabrielBB/xvfb-action@v1
with:
Expand Down
8 changes: 0 additions & 8 deletions .github/workflows/tagged_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
- name: Setup Docker
if: ${{matrix.os == 'ubuntu-latest'}}
run: |
docker pull s1hofmann/nut-ci:latest
docker run -it -d --name nut-ci --shm-size 8gb --user $(id -u):$(id -g) -v ${PWD}:${PWD}:rw s1hofmann/nut-ci:latest bash
- name: Install
run: npm ci
- name: Compile
Expand All @@ -35,9 +30,6 @@ jobs:
run: |
npx playwright install --with-deps
npm test
- name: Run Docker E2E tests
if: ${{matrix.os == 'ubuntu-latest'}}
run: docker exec nut-ci bash -c "bash $PWD/.build/build.sh ${PWD} ${{matrix.node}}"
- name: Run Electron e2e test subpackage
uses: GabrielBB/xvfb-action@v1
with:
Expand Down
13 changes: 0 additions & 13 deletions lib/clipboard.class.e2e.spec.ts

This file was deleted.

9 changes: 7 additions & 2 deletions lib/expect/jest.matcher.function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { toBeAt } from "./matchers/toBeAt.function";
import { toBeIn } from "./matchers/toBeIn.function";
import { toShow } from "./matchers/toShow.function";
import { FindInput } from "../screen.class";
import { RGBA } from "../rgba.class";
import { toHaveColor } from "./matchers/toHaveColor.function";
import { OptionalSearchParameters } from "../optionalsearchparameters.class";

declare global {
namespace jest {
interface Matchers<R> {
toBeAt: (position: Point) => ReturnType<typeof toBeAt>;
toBeIn: (region: Region) => ReturnType<typeof toBeIn>;
// @ts-ignore
toShow: (
toShow: <PROVIDER_DATA>(
needle: FindInput,
confidence?: number
parameters?: OptionalSearchParameters<PROVIDER_DATA>,
) => ReturnType<typeof toShow>;
toHaveColor: (color: RGBA) => ReturnType<typeof toHaveColor>;
}
}
}
Expand All @@ -23,4 +27,5 @@ export const jestMatchers = {
toBeAt,
toBeIn,
toShow,
toHaveColor,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@ import { mouse } from "../../../index";
import { Point } from "../../point.class";
import { toBeAt } from "./toBeAt.function";

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

const targetPoint = new Point(100, 100);

describe(".toBeAt", () => {
beforeEach(() => {
mouse.setPosition(targetPoint);
});

it("should succeed when cursor is at right position.", async () => {
mouse.getPosition = jest.fn(() => Promise.resolve(targetPoint));
const result = await toBeAt(mouse, targetPoint);
expect(result.pass).toBeTruthy();
});

it("should fail when cursor is at wrong position.", async () => {
mouse.getPosition = jest.fn(() => Promise.resolve(targetPoint));
const result = await toBeAt(mouse, new Point(10, 10));
expect(result.pass).toBeFalsy();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,19 @@ import { Point } from "../../point.class";
import { Region } from "../../region.class";
import { toBeIn } from "./toBeIn.function";

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

const targetPoint = new Point(400, 400);

describe(".toBeIn", () => {
beforeEach(() => {
mouse.setPosition(targetPoint);
});

it("should succeed when cursor is within correct region.", async () => {
const targetRegion = new Region(350, 350, 100, 100);
mouse.getPosition = jest.fn(() => Promise.resolve(targetPoint));
const result = await toBeIn(mouse, targetRegion);
expect(result.pass).toBeTruthy();
});

it("should fail when cursor is outside of search region.", async () => {
const targetRegion = new Region(0, 0, 100, 100);
mouse.setPosition(targetPoint);
mouse.getPosition = jest.fn(() => Promise.resolve(targetPoint));
const result = await toBeIn(mouse, targetRegion);
expect(result.pass).toBeFalsy();
});
Expand Down
66 changes: 66 additions & 0 deletions lib/expect/matchers/toHaveColor.function.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { RGBA, screen } from "../../../index";
import { Point } from "../../point.class";
import { mockPartial } from "sneer";
import { toHaveColor } from "./toHaveColor.function";

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

const targetPoint = new Point(400, 400);

describe(".toHaveColor", () => {
it("should succeed when screen pixel has the correct RGBA value", async () => {
// GIVEN
screen.colorAt = mockPartial(() => {
return new RGBA(0, 0, 0, 0);
});

// WHEN
const result = await toHaveColor(targetPoint, new RGBA(0, 0, 0, 0));

// THEN
expect(result.pass).toBeTruthy();
});

it("should fail when the screen pixel has the incorrect RGBA value", async () => {
// GIVEN
screen.colorAt = mockPartial(() => {
return new RGBA(255, 0, 5, 0);
});

// WHEN
const result = await toHaveColor(targetPoint, new RGBA(0, 0, 0, 0));

// THEN
expect(result.pass).toBeFalsy();
});

it("should succeed when the screen pixel has the correct RGBA value", async () => {
// GIVEN
screen.colorAt = mockPartial(() => {
return new RGBA(0, 0, 0, 0);
});
expect.extend({
toHaveColor,
});

// WHEN

// THEN
await expect(targetPoint).toHaveColor(new RGBA(0, 0, 0, 0));
});

it("should succeed when the screen pixel has the incorrect RGBA value", async () => {
// GIVEN
screen.colorAt = mockPartial(() => {
return new RGBA(255, 0, 5, 0);
});
expect.extend({
toHaveColor,
});

// WHEN

// THEN
await expect(targetPoint).not.toHaveColor(new RGBA(0, 0, 0, 0));
});
});
19 changes: 19 additions & 0 deletions lib/expect/matchers/toHaveColor.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Point, RGBA, screen } from "../../../index";

export const toHaveColor = async (received: Point, needle: RGBA) => {
const color = await screen.colorAt(received);
const match = color.toHex() === needle.toHex();
if (match) {
return {
message: () =>
`Expected pixel ${received.toString()} not to to have color ${needle.toHex()}`,
pass: true,
};
} else {
return {
message: () =>
`Expected pixel ${received.toString()} to have color ${needle.toHex()} but is ${color.toHex()}`,
pass: false,
};
}
};
55 changes: 36 additions & 19 deletions lib/expect/matchers/toShow.function.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
import { FindInput, ScreenClass } from "../../screen.class";
import { OptionalSearchParameters } from "../../optionalsearchparameters.class";
import { isRegion, Region } from "../../region.class";
import { screen } from "../../../index";

export const toShow = async (
received: ScreenClass,
export const toShow = async <PROVIDER_DATA>(
received: ScreenClass | Region,
needle: FindInput,
confidence?: number
parameters?: OptionalSearchParameters<PROVIDER_DATA>,
) => {
let locationParams;
if (confidence) {
locationParams = new OptionalSearchParameters();
locationParams.confidence = confidence;
}
const identifier = (await needle).id;
try {
await received.find(needle, locationParams);
return {
message: () => `Expected screen to not show ${identifier}`,
pass: true,
};
} catch (err) {
return {
message: () => `Screen is not showing ${identifier}: ${err}`,
pass: false,
};
if (isRegion(received)) {
if (parameters != null) {
parameters.searchRegion = received;
} else {
parameters = { searchRegion: received };
}
try {
await screen.find(needle, parameters);
return {
message: () => `Expected screen to not show ${identifier}`,
pass: true,
};
} catch (err) {
return {
message: () => `Screen is not showing ${identifier}: ${err}`,
pass: false,
};
}
} else {
try {
await received.find(needle, parameters);
return {
message: () => `Expected screen to not show ${identifier}`,
pass: true,
};
} catch (err) {
return {
message: () => `Screen is not showing ${identifier}: ${err}`,
pass: false,
};
}
}
};
Loading

0 comments on commit db81b6e

Please sign in to comment.