diff --git a/apps/desktop/src/main/lib/window-state/bounds-validation.test.ts b/apps/desktop/src/main/lib/window-state/bounds-validation.test.ts index 8b89325ac49..febf5141b10 100644 --- a/apps/desktop/src/main/lib/window-state/bounds-validation.test.ts +++ b/apps/desktop/src/main/lib/window-state/bounds-validation.test.ts @@ -1,9 +1,35 @@ -import { beforeEach, describe, expect, it, type mock } from "bun:test"; -import { screen } from "electron"; import { - getInitialWindowBounds, - isVisibleOnAnyDisplay, -} from "./bounds-validation"; + beforeEach, + describe, + expect, + it, + type mock as MockType, + mock, +} from "bun:test"; + +// Mock electron with screen API before importing anything that uses it +const mockScreen = { + getPrimaryDisplay: mock(() => ({ + workAreaSize: { width: 1920, height: 1080 }, + bounds: { x: 0, y: 0, width: 1920, height: 1080 }, + })), + getAllDisplays: mock(() => [ + { + bounds: { x: 0, y: 0, width: 1920, height: 1080 }, + workAreaSize: { width: 1920, height: 1080 }, + }, + ]), +}; + +mock.module("electron", () => ({ + screen: mockScreen, +})); + +// Import module after mocks are set up +const { getInitialWindowBounds, isVisibleOnAnyDisplay } = await import( + "./bounds-validation" +); +const screen = mockScreen; const MIN_VISIBLE_OVERLAP = 50; const MIN_WINDOW_SIZE = 400; @@ -11,7 +37,7 @@ const MIN_WINDOW_SIZE = 400; describe("isVisibleOnAnyDisplay", () => { describe("single display setup", () => { beforeEach(() => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, ]); }); @@ -99,7 +125,7 @@ describe("isVisibleOnAnyDisplay", () => { describe("multi-display setup", () => { beforeEach(() => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, { bounds: { x: 1920, y: 0, width: 1920, height: 1080 } }, ]); @@ -126,7 +152,7 @@ describe("isVisibleOnAnyDisplay", () => { describe("secondary display with offset", () => { beforeEach(() => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, { bounds: { x: 960, y: 1080, width: 1920, height: 1080 } }, ]); @@ -147,7 +173,7 @@ describe("isVisibleOnAnyDisplay", () => { describe("display to the left (negative coordinates)", () => { beforeEach(() => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, { bounds: { x: -1920, y: 0, width: 1920, height: 1080 } }, ]); @@ -162,14 +188,16 @@ describe("isVisibleOnAnyDisplay", () => { describe("edge cases", () => { it("should return false when no displays connected", () => { - (screen.getAllDisplays as ReturnType).mockReturnValue([]); + (screen.getAllDisplays as ReturnType).mockReturnValue( + [], + ); expect( isVisibleOnAnyDisplay({ x: 100, y: 100, width: 800, height: 600 }), ).toBe(false); }); it("should return true for zero-size window if position is valid (size validation is separate)", () => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, ]); expect( @@ -181,10 +209,10 @@ describe("isVisibleOnAnyDisplay", () => { describe("getInitialWindowBounds", () => { beforeEach(() => { - (screen.getPrimaryDisplay as ReturnType).mockReturnValue({ + (screen.getPrimaryDisplay as ReturnType).mockReturnValue({ workAreaSize: { width: 1920, height: 1080 }, }); - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, ]); }); @@ -319,9 +347,11 @@ describe("getInitialWindowBounds", () => { describe("DPI/resolution changes", () => { it("should handle resolution decrease gracefully", () => { - (screen.getPrimaryDisplay as ReturnType).mockReturnValue({ - workAreaSize: { width: 1280, height: 720 }, - }); + (screen.getPrimaryDisplay as ReturnType).mockReturnValue( + { + workAreaSize: { width: 1280, height: 720 }, + }, + ); const result = getInitialWindowBounds({ x: 0, @@ -336,9 +366,11 @@ describe("getInitialWindowBounds", () => { }); it("should clamp to work area even if smaller than MIN_WINDOW_SIZE", () => { - (screen.getPrimaryDisplay as ReturnType).mockReturnValue({ - workAreaSize: { width: 300, height: 200 }, - }); + (screen.getPrimaryDisplay as ReturnType).mockReturnValue( + { + workAreaSize: { width: 300, height: 200 }, + }, + ); const result = getInitialWindowBounds({ x: 0, @@ -355,7 +387,7 @@ describe("getInitialWindowBounds", () => { describe("multi-monitor scenarios", () => { beforeEach(() => { - (screen.getAllDisplays as ReturnType).mockReturnValue([ + (screen.getAllDisplays as ReturnType).mockReturnValue([ { bounds: { x: 0, y: 0, width: 1920, height: 1080 } }, { bounds: { x: 1920, y: 0, width: 1920, height: 1080 } }, ]); diff --git a/bun.lock b/bun.lock index c259823837a..5e423dced2d 100644 --- a/bun.lock +++ b/bun.lock @@ -121,7 +121,7 @@ }, "apps/desktop": { "name": "@superset/desktop", - "version": "0.0.50", + "version": "0.0.51", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -156,7 +156,7 @@ "@xterm/addon-unicode11": "^0.8.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/addon-webgl": "^0.18.0", - "@xterm/headless": "5.5.0", + "@xterm/headless": "^5.5.0", "@xterm/xterm": "^5.5.0", "better-sqlite3": "12.5.0", "bindings": "^1.5.0",