mirror of
https://github.com/Bismuth-Forge/bismuth.git
synced 2024-09-17 11:37:10 +03:00
test: ✅ add a few basic tests with mocks
Tests directory probably will be used for integration tests.
This commit is contained in:
parent
b759156b3c
commit
13b1987ee0
5
config.ts
Normal file
5
config.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: none
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "jest-ts-auto-mock";
|
14
package.json
14
package.json
@ -18,13 +18,16 @@
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"husky": "^7.0.2",
|
||||
"jest": "^27.1.0",
|
||||
"jest": "^27.2.0",
|
||||
"jest-ts-auto-mock": "^2.0.0",
|
||||
"lint-staged": "^11.1.2",
|
||||
"prettier": "2.3.2",
|
||||
"ts-auto-mock": "^3.5.0",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ttypescript": "^1.5.12",
|
||||
"typedoc": "^0.21.6",
|
||||
"typedoc-plugin-rename-defaults": "^0.3.0",
|
||||
"typescript": "^4.3.5"
|
||||
"typescript": "^4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "bin/clean.sh",
|
||||
@ -59,9 +62,16 @@
|
||||
"homepage": "https://github.com/gikari/bismuth#readme",
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
"transform": {
|
||||
".(ts|tsx)": "ts-jest"
|
||||
},
|
||||
"testEnvironment": "node",
|
||||
"globals": {
|
||||
"ts-jest": {
|
||||
"compiler": "ttypescript",
|
||||
"setupFiles": [
|
||||
"<rootDir>config.ts"
|
||||
],
|
||||
"diagnostics": {
|
||||
"ignoreCodes": [
|
||||
"TS151001"
|
||||
|
@ -131,7 +131,11 @@ export class KWinWindow implements DriverWindow {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
public commit(geometry?: Rect, noBorder?: boolean, keepAbove?: boolean) {
|
||||
public commit(
|
||||
geometry?: Rect,
|
||||
noBorder?: boolean,
|
||||
keepAbove?: boolean
|
||||
): void {
|
||||
this.debug.debugObj(() => [
|
||||
"KWinWindow#commit",
|
||||
{ geometry, noBorder, keepAbove },
|
||||
|
86
src/engine/index.test.ts
Normal file
86
src/engine/index.test.ts
Normal file
@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { createMock } from "ts-auto-mock";
|
||||
import { On, method } from "ts-auto-mock/extension";
|
||||
|
||||
import { TilingEngine } from ".";
|
||||
import Config from "../config";
|
||||
import { Controller } from "../controller";
|
||||
import { DriverSurface } from "../driver/surface";
|
||||
import { DriverWindow } from "../driver/window";
|
||||
|
||||
import Debug from "../util/debug";
|
||||
import Rect from "../util/rect";
|
||||
import TileLayout from "./layout/tile_layout";
|
||||
import LayoutStore from "./layout_store";
|
||||
import Window, { WindowState } from "./window";
|
||||
import WindowStore from "./window_store";
|
||||
|
||||
describe("arrange", () => {
|
||||
it("happens on all screens", () => {
|
||||
const screenMock = createMock<DriverSurface>();
|
||||
const fakeScreens = [screenMock, screenMock, screenMock, screenMock];
|
||||
|
||||
const controllerMock = createMock<Controller>({ screens: fakeScreens });
|
||||
const debugMock = createMock<Debug>();
|
||||
const configMock = createMock<Config>();
|
||||
const engine = new TilingEngine(controllerMock, configMock, debugMock);
|
||||
|
||||
jest.spyOn(engine, "arrangeScreen").mockReturnValue();
|
||||
|
||||
engine.arrange();
|
||||
|
||||
expect(engine.arrangeScreen).toBeCalledTimes(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe("arrangeScreen", () => {
|
||||
describe("window states are correctly changed", () => {
|
||||
// Arrange
|
||||
const controllerMock = createMock<Controller>();
|
||||
const debugMock = createMock<Debug>();
|
||||
const configMock = createMock<Config>();
|
||||
const engine = new TilingEngine(controllerMock, configMock, debugMock);
|
||||
|
||||
const window1 = createMock<Window>({
|
||||
shouldFloat: false,
|
||||
state: WindowState.Undecided,
|
||||
});
|
||||
|
||||
const window2 = createMock<Window>({
|
||||
shouldFloat: true,
|
||||
state: WindowState.Undecided,
|
||||
});
|
||||
|
||||
const windowsStoreMock = createMock<WindowStore>({
|
||||
getVisibleWindows: () => [window1, window2],
|
||||
getVisibleTileables: () => [],
|
||||
});
|
||||
|
||||
engine.windows = windowsStoreMock;
|
||||
|
||||
const layoutStoreMock = createMock<LayoutStore>({
|
||||
getCurrentLayout: () => createMock<TileLayout>(),
|
||||
});
|
||||
engine.layouts = layoutStoreMock;
|
||||
|
||||
jest
|
||||
.spyOn(TilingEngine.prototype as any, "getTilingArea")
|
||||
.mockReturnValue(createMock<Rect>());
|
||||
|
||||
const mockSurface = createMock<DriverSurface>();
|
||||
|
||||
// Act
|
||||
engine.arrangeScreen(mockSurface);
|
||||
|
||||
// Assert
|
||||
it("sets all undecided windows to tiled state, when they should not float", () => {
|
||||
expect(window1.state).toEqual(WindowState.Tiled);
|
||||
});
|
||||
it("sets all undecided windows to float state, when they should float", () => {
|
||||
expect(window2.state).toEqual(WindowState.Floating);
|
||||
});
|
||||
});
|
||||
});
|
@ -21,6 +21,7 @@ import { overlap, wrapIndex } from "../util/func";
|
||||
import Config from "../config";
|
||||
import Debug from "../util/debug";
|
||||
import qmlSetTimeout from "../util/timer";
|
||||
import { WindowsLayout } from "./layout";
|
||||
|
||||
export type Direction = "up" | "down" | "left" | "right";
|
||||
|
||||
@ -225,7 +226,7 @@ export class TilingEngine implements Engine {
|
||||
/**
|
||||
* Arrange tiles on all screens.
|
||||
*/
|
||||
public arrange() {
|
||||
public arrange(): void {
|
||||
this.debug.debug(() => "arrange");
|
||||
|
||||
this.controller.screens.forEach((driverSurface: DriverSurface) => {
|
||||
@ -234,48 +235,44 @@ export class TilingEngine implements Engine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Arrange tiles on a screen.
|
||||
* Arrange tiles on one screen
|
||||
*
|
||||
* @param screenSurface screen's surface, on which windows should be arranged
|
||||
*/
|
||||
public arrangeScreen(srf: DriverSurface) {
|
||||
const layout = this.layouts.getCurrentLayout(srf);
|
||||
public arrangeScreen(screenSurface: DriverSurface) {
|
||||
const layout = this.layouts.getCurrentLayout(screenSurface);
|
||||
|
||||
const workingArea = srf.workingArea;
|
||||
const workingArea = screenSurface.workingArea;
|
||||
const tilingArea = this.getTilingArea(workingArea, layout);
|
||||
|
||||
let tilingArea: Rect;
|
||||
if (this.config.monocleMaximize && layout instanceof MonocleLayout)
|
||||
tilingArea = workingArea;
|
||||
else
|
||||
tilingArea = workingArea.gap(
|
||||
this.config.screenGapLeft,
|
||||
this.config.screenGapRight,
|
||||
this.config.screenGapTop,
|
||||
this.config.screenGapBottom
|
||||
);
|
||||
|
||||
const visibles = this.windows.getVisibleWindows(srf);
|
||||
const visibleWindows = this.windows.getVisibleWindows(screenSurface);
|
||||
this.debug.debugObj(() => [
|
||||
"arrangeScreen",
|
||||
{
|
||||
layout,
|
||||
srf,
|
||||
visibles: visibles.length,
|
||||
screenSurface,
|
||||
visibles: visibleWindows.length,
|
||||
},
|
||||
]);
|
||||
|
||||
visibles.forEach((window) => {
|
||||
if (window.state === WindowState.Undecided)
|
||||
window.state = window.shouldFloat
|
||||
? WindowState.Floating
|
||||
: WindowState.Tiled;
|
||||
// Set correct window state for new windows
|
||||
visibleWindows.forEach((win: Window) => {
|
||||
if (win.state === WindowState.Undecided) {
|
||||
win.state = win.shouldFloat ? WindowState.Floating : WindowState.Tiled;
|
||||
}
|
||||
});
|
||||
|
||||
const tileables = this.windows.getVisibleTileables(srf);
|
||||
if (this.config.maximizeSoleTile && tileables.length === 1) {
|
||||
tileables[0].state = WindowState.Maximized;
|
||||
tileables[0].geometry = workingArea;
|
||||
} else if (tileables.length > 0)
|
||||
layout.apply(this.controller, tileables, tilingArea);
|
||||
const tileableWindows = this.windows.getVisibleTileables(screenSurface);
|
||||
|
||||
// Maximize sole tile if enabled or apply the current layout as expected
|
||||
if (this.config.maximizeSoleTile && tileableWindows.length === 1) {
|
||||
tileableWindows[0].state = WindowState.Maximized;
|
||||
tileableWindows[0].geometry = workingArea;
|
||||
} else if (tileableWindows.length > 0) {
|
||||
layout.apply(this.controller, tileableWindows, tilingArea);
|
||||
}
|
||||
|
||||
// If enabled, limit the windows' width
|
||||
if (
|
||||
this.config.limitTileWidthRatio > 0 &&
|
||||
!(layout instanceof MonocleLayout)
|
||||
@ -283,7 +280,7 @@ export class TilingEngine implements Engine {
|
||||
const maxWidth = Math.floor(
|
||||
workingArea.height * this.config.limitTileWidthRatio
|
||||
);
|
||||
tileables
|
||||
tileableWindows
|
||||
.filter((tile) => tile.tiled && tile.geometry.width > maxWidth)
|
||||
.forEach((tile) => {
|
||||
const g = tile.geometry;
|
||||
@ -296,8 +293,9 @@ export class TilingEngine implements Engine {
|
||||
});
|
||||
}
|
||||
|
||||
visibles.forEach((window) => window.commit());
|
||||
this.debug.debugObj(() => ["arrangeScreen/finished", { srf }]);
|
||||
// Commit window assigned properties
|
||||
visibleWindows.forEach((win: Window) => win.commit());
|
||||
this.debug.debugObj(() => ["arrangeScreen/finished", { screenSurface }]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,4 +630,26 @@ export class TilingEngine implements Engine {
|
||||
public showNotification(text: string): void {
|
||||
this.controller.showNotification(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tiling area for the given working area and the windows layout.
|
||||
*
|
||||
* Tiling area is the area we are allowed to put windows in, not counting the inner gaps
|
||||
* between them. I.e. working are without gaps.
|
||||
*
|
||||
* @param workingArea area in which we are allowed to work. @see DriverSurface#workingArea
|
||||
* @param layout windows layout used
|
||||
*/
|
||||
private getTilingArea(workingArea: Rect, layout: WindowsLayout): Rect {
|
||||
if (this.config.monocleMaximize && layout instanceof MonocleLayout) {
|
||||
return workingArea;
|
||||
} else {
|
||||
return workingArea.gap(
|
||||
this.config.screenGapLeft,
|
||||
this.config.screenGapRight,
|
||||
this.config.screenGapTop,
|
||||
this.config.screenGapBottom
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ export default class Window {
|
||||
this.weightMap = {};
|
||||
}
|
||||
|
||||
public commit() {
|
||||
public commit(): void {
|
||||
const state = this.state;
|
||||
this.debug.debugObj(() => ["Window#commit", { state: WindowState[state] }]);
|
||||
switch (state) {
|
||||
|
@ -1,10 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
|
||||
// SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
describe("it just works", function () {
|
||||
it("just works", function () {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
@ -8,7 +8,13 @@
|
||||
"alwaysStrict": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"module": "ES6"
|
||||
"module": "ES6",
|
||||
"plugins": [
|
||||
{
|
||||
"transform": "ts-auto-mock/transformer",
|
||||
"cacheBetweenTests": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"typedocOptions": {
|
||||
"entryPoints": ["src"]
|
||||
|
Loading…
Reference in New Issue
Block a user