|
@@ -1,4 +1,4 @@
|
|
|
-import { nativeImage } from 'electron';
|
|
|
+import { NativeImage, nativeImage } from 'electron';
|
|
|
import { app, BrowserWindow, BrowserView, dialog, ipcMain, OnBeforeSendHeadersListenerDetails, net, protocol, screen, webContents, webFrameMain, session, WebContents, WebFrameMain } from 'electron/main';
|
|
|
|
|
|
import { expect } from 'chai';
|
|
@@ -16,7 +16,8 @@ import { setTimeout } from 'node:timers/promises';
|
|
|
import * as nodeUrl from 'node:url';
|
|
|
|
|
|
import { emittedUntil, emittedNTimes } from './lib/events-helpers';
|
|
|
-import { HexColors, hasCapturableScreen, ScreenCapture } from './lib/screen-helpers';
|
|
|
+import { previewNativeImage } from './lib/image-helpers';
|
|
|
+import { HexColors, hasCapturableScreen, ScreenCapture, getPixelColor } from './lib/screen-helpers';
|
|
|
import { ifit, ifdescribe, defer, listen, waitUntil } from './lib/spec-helpers';
|
|
|
import { closeWindow, closeAllWindows } from './lib/window-helpers';
|
|
|
|
|
@@ -6439,6 +6440,9 @@ describe('BrowserWindow module', () => {
|
|
|
});
|
|
|
|
|
|
describe('offscreen rendering', () => {
|
|
|
+ // Toggle to display windows previewing OSR NativeImage results
|
|
|
+ const DEBUG_OFFSCREEN = false;
|
|
|
+
|
|
|
let w: BrowserWindow;
|
|
|
beforeEach(function () {
|
|
|
w = new BrowserWindow({
|
|
@@ -6453,18 +6457,54 @@ describe('BrowserWindow module', () => {
|
|
|
});
|
|
|
afterEach(closeAllWindows);
|
|
|
|
|
|
+ const preview = async (image: NativeImage) => {
|
|
|
+ if (DEBUG_OFFSCREEN) {
|
|
|
+ await previewNativeImage(image);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
it('creates offscreen window with correct size', async () => {
|
|
|
const paint = once(w.webContents, 'paint') as Promise<[any, Electron.Rectangle, Electron.NativeImage]>;
|
|
|
w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'));
|
|
|
const [, , data] = await paint;
|
|
|
expect(data.constructor.name).to.equal('NativeImage');
|
|
|
expect(data.isEmpty()).to.be.false('data is empty');
|
|
|
+ await preview(data);
|
|
|
const size = data.getSize();
|
|
|
const { scaleFactor } = screen.getPrimaryDisplay();
|
|
|
expect(size.width).to.be.closeTo(100 * scaleFactor, 2);
|
|
|
expect(size.height).to.be.closeTo(100 * scaleFactor, 2);
|
|
|
});
|
|
|
|
|
|
+ it('creates offscreen window with opaque background', async () => {
|
|
|
+ w.setBackgroundColor(HexColors.RED);
|
|
|
+ const paint = once(w.webContents, 'paint') as Promise<[any, Electron.Rectangle, Electron.NativeImage]>;
|
|
|
+ w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'));
|
|
|
+ const [, , data] = await paint;
|
|
|
+ await preview(data);
|
|
|
+ expect(getPixelColor(data, { x: 0, y: 0 }, true)).to.equal('#ff0000ff');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('creates offscreen window with transparent background', async () => {
|
|
|
+ w.setBackgroundColor(HexColors.TRANSPARENT);
|
|
|
+ const paint = once(w.webContents, 'paint') as Promise<[any, Electron.Rectangle, Electron.NativeImage]>;
|
|
|
+ w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'));
|
|
|
+ const [, , data] = await paint;
|
|
|
+ await preview(data);
|
|
|
+ expect(getPixelColor(data, { x: 0, y: 0 }, true)).to.equal(HexColors.TRANSPARENT);
|
|
|
+ });
|
|
|
+
|
|
|
+ // Semi-transparent background is not supported
|
|
|
+ it.skip('creates offscreen window with semi-transparent background', async () => {
|
|
|
+ const bgColor = '#66ffffff'; // ARGB
|
|
|
+ w.setBackgroundColor(bgColor);
|
|
|
+ const paint = once(w.webContents, 'paint') as Promise<[any, Electron.Rectangle, Electron.NativeImage]>;
|
|
|
+ w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'));
|
|
|
+ const [, , data] = await paint;
|
|
|
+ await preview(data);
|
|
|
+ expect(getPixelColor(data, { x: 0, y: 0 }, true)).to.equal(bgColor);
|
|
|
+ });
|
|
|
+
|
|
|
it('does not crash after navigation', () => {
|
|
|
w.webContents.loadURL('about:blank');
|
|
|
w.loadFile(path.join(fixtures, 'api', 'offscreen-rendering.html'));
|