Skip to content
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

Bugfix/559/limit window region to main screen dimensions #561

Merged
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
14 changes: 12 additions & 2 deletions core/nut.js/lib/window.class.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { Window } from "./window.class";
import { ProviderRegistry, WindowProviderInterface } from "@nut-tree/provider-interfaces";
import { ProviderRegistry, ScreenProviderInterface, WindowProviderInterface } from "@nut-tree/provider-interfaces";
import { mockPartial } from "sneer";
import { Region } from "@nut-tree/shared";

describe("Window class", () => {
it("should retrieve the window region via provider", async () => {
// GIVEN
const windowMock = jest.fn();
const windowMock = jest.fn(() => {
return Promise.resolve(new Region(10, 10, 100, 100));
});
const providerRegistryMock = mockPartial<ProviderRegistry>({
getWindow(): WindowProviderInterface {
return mockPartial<WindowProviderInterface>({
getWindowRegion: windowMock
});
},
getScreen(): ScreenProviderInterface {
return mockPartial<ScreenProviderInterface>({
screenSize(): Promise<Region> {
return Promise.resolve(new Region(0, 0, 1920, 1080));
}
});
}
});
const mockWindowHandle = 123;
Expand Down
28 changes: 27 additions & 1 deletion core/nut.js/lib/window.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,33 @@ export class Window implements WindowInterface {
}

async getRegion(): Promise<Region> {
return this.providerRegistry.getWindow().getWindowRegion(this.windowHandle);
const region = await this.providerRegistry.getWindow().getWindowRegion(this.windowHandle);
const mainWindowRegion = await this.providerRegistry.getScreen().screenSize();
if (region.left < 0) {
region.width = region.width + region.left;
region.left = 0;
}
if (region.top < 0) {
region.height = region.height + region.top;
region.top = 0;
}
const rightWindowBound = region.left + region.width;
if (rightWindowBound > mainWindowRegion.width) {
const excessWidth = rightWindowBound - mainWindowRegion.width;
region.width = region.width - excessWidth;
}
const bottomWindowBound = region.top + region.height;
if (bottomWindowBound > mainWindowRegion.height) {
const excessHeight = bottomWindowBound - mainWindowRegion.height;
region.height = region.height - excessHeight;
}
if (region.width < 0) {
region.width = 0;
}
if (region.height < 0) {
region.height = 0;
}
return region;
}

async move(newOrigin: Point) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const POS_X = 50;
const POS_Y = 100;
const WIDTH = 400;
const HEIGTH = 300;
const HEIGHT = 300;
const TITLE = "libnut window test";

module.exports = {
POS_X,
POS_Y,
WIDTH,
HEIGTH,
HEIGHT,
TITLE,
};
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions examples/window-test/main.js → e2e/window-test/main.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const { app, ipcMain, BrowserWindow } = require("electron");
const path = require("path");
const { POS_X, POS_Y, WIDTH, HEIGTH } = require("./constants");
const { POS_X, POS_Y, WIDTH, HEIGHT } = require("./constants");

function createWindow() {
const mainWindow = new BrowserWindow({
width: WIDTH,
height: HEIGTH,
height: HEIGHT,
alwaysOnTop: true,
webPreferences: {
nodeIntegration: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
},
"scripts": {
"pretest": "pnpx playwright install --with-deps",
"test": "jest"
"test": "jest",
"coverage": "jest --coverage --runInBand --logHeapUsage",
"coverage:clean": "rimraf coverage"
},
"devDependencies": {
"@nut-tree/nut-js": "workspace:*",
"@playwright/test": "1.41.2",
"electron": "28.2.3",
"electron": "28.0.0",
"jest": "29.7.0",
"jest-playwright-preset": "4.0.0",
"playwright": "1.41.2"
Expand Down
File renamed without changes.
File renamed without changes.
40 changes: 37 additions & 3 deletions examples/window-test/test.spec.js → e2e/window-test/test.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { _electron: electron } = require("playwright");
const { sleep, getActiveWindow, getWindows } = require("@nut-tree/nut-js");
const { POS_X, POS_Y, WIDTH, HEIGTH, TITLE } = require("./constants");
const { sleep, getActiveWindow, screen, getWindows } = require("@nut-tree/nut-js");
const { POS_X, POS_Y, WIDTH, HEIGHT, TITLE } = require("./constants");

let app;
let page;
Expand Down Expand Up @@ -57,7 +57,7 @@ describe("getActiveWindow", () => {
expect(activeWindowRegion.left).toBe(POS_X);
expect(activeWindowRegion.top).toBe(POS_Y);
expect(activeWindowRegion.width).toBe(WIDTH);
expect(activeWindowRegion.height).toBe(HEIGTH);
expect(activeWindowRegion.height).toBe(HEIGHT);
});

it("should determine correct coordinates for our application after moving the window", async () => {
Expand Down Expand Up @@ -93,6 +93,40 @@ describe("getActiveWindow", () => {
});
});

describe("window regions", () => {
it("should crop window coordinates on main screen boundaries to the left", async () => {
// GIVEN
const newLeft = -40;

// WHEN
const foregroundWindow = await getActiveWindow();
await foregroundWindow.move({ x: newLeft, y: POS_Y });
await sleep(1000);
const activeWindowRegion = await foregroundWindow.region;

// THEN
expect(activeWindowRegion.left).toBe(0);
expect(activeWindowRegion.width).toBe(WIDTH + newLeft);
});

it("should crop window coordinates on main screen boundaries to the right", async () => {
// GIVEN
const screenWidth = await screen.width();
const delta = 40;
const newLeft = screenWidth - delta;

// WHEN
const foregroundWindow = await getActiveWindow();
await foregroundWindow.move({ x: newLeft, y: POS_Y });
await sleep(1000);
const activeWindowRegion = await foregroundWindow.region;

// THEN
expect(activeWindowRegion.left).toBe(newLeft);
expect(activeWindowRegion.width).toBe(delta);
});
});

afterEach(async () => {
if (app) {
await app.close();
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"workspaces": [
"core/*",
"providers/*",
"examples/*"
"examples/*",
"e2e/*"
],
"dependencies": {},
"devDependencies": {
Expand Down
46 changes: 23 additions & 23 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ packages:
- 'core/*'
- 'providers/*'
- 'examples/*'
- 'e2e/*'
Loading