diff --git a/fluxer_desktop/src/main/DisplayMedia.ts b/fluxer_desktop/src/main/DisplayMedia.ts index c6d034632..4dd75c7a6 100644 --- a/fluxer_desktop/src/main/DisplayMedia.ts +++ b/fluxer_desktop/src/main/DisplayMedia.ts @@ -128,7 +128,7 @@ function consumeWaylandPortalSurfacePreference(): DisplayMediaPortalSurfacePrefe return preference; } -export const DISPLAY_MEDIA_PORTAL_EMPTY_CHANNEL = 'display-media-portal-empty'; +const DISPLAY_MEDIA_PORTAL_EMPTY_CHANNEL = 'display-media-portal-empty'; type WaylandPortalUnavailableReason = 'empty' | 'error'; @@ -152,7 +152,7 @@ async function defaultWaylandPortalSourceProvider( return desktopCapturer.getSources({types}); } -export async function resolveWaylandPortalDisplayMedia( +async function resolveWaylandPortalDisplayMedia( context: WaylandPortalResolutionContext, ): Promise { const {requestId, preference, getSources, notifyUnavailable} = context; diff --git a/fluxer_desktop/src/main/ScreenShareDesktopFlags.test.ts b/fluxer_desktop/src/main/ScreenShareDesktopFlags.test.ts deleted file mode 100644 index 0456b9c90..000000000 --- a/fluxer_desktop/src/main/ScreenShareDesktopFlags.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-or-later - -import assert from 'node:assert/strict'; -import test from 'node:test'; - -interface FakeCommandLineState { - switches: Map; -} - -function createFakeCommandLine(initial: Record = {}) { - const state: FakeCommandLineState = {switches: new Map()}; - for (const [name, value] of Object.entries(initial)) { - state.switches.set(name, value === true ? '' : value); - } - return { - state, - appendSwitch(name: string, value?: string): void { - state.switches.set(name, value ?? ''); - }, - getSwitchValue(name: string): string { - return state.switches.get(name) ?? ''; - }, - hasSwitch(name: string): boolean { - return state.switches.has(name); - }, - }; -} - -const electronCommandLine = createFakeCommandLine(); - -test.mock.module('electron', { - namedExports: { - app: {commandLine: electronCommandLine}, - desktopCapturer: {getSources: async () => []}, - ipcMain: {handle: () => {}, on: () => {}}, - screen: {getAllDisplays: () => []}, - BrowserWindow: {getAllWindows: () => []}, - }, -}); - -test.mock.module('electron-log', { - defaultExport: { - info: () => {}, - warn: () => {}, - error: () => {}, - debug: () => {}, - }, -}); - -const {addLinuxScreenCapturePipeWireFeature, appendLinuxOzonePlatformHint, hasConfiguredOzonePlatformSwitch} = - await import('./ChromiumRuntime'); - -const {resolveWaylandPortalDisplayMedia, DISPLAY_MEDIA_PORTAL_EMPTY_CHANNEL} = await import('./DisplayMedia'); - -function withPlatform(platform: NodeJS.Platform, run: () => T): T { - const original = Object.getOwnPropertyDescriptor(process, 'platform'); - Object.defineProperty(process, 'platform', {configurable: true, value: platform}); - try { - return run(); - } finally { - if (original) { - Object.defineProperty(process, 'platform', original); - } - } -} - -test('addLinuxScreenCapturePipeWireFeature enables WebRTCPipeWireCapturer only on Linux', () => { - withPlatform('linux', () => { - const features = new Set(); - addLinuxScreenCapturePipeWireFeature(features); - assert.ok(features.has('WebRTCPipeWireCapturer')); - }); - withPlatform('darwin', () => { - const features = new Set(); - addLinuxScreenCapturePipeWireFeature(features); - assert.equal(features.has('WebRTCPipeWireCapturer'), false); - }); - withPlatform('win32', () => { - const features = new Set(); - addLinuxScreenCapturePipeWireFeature(features); - assert.equal(features.has('WebRTCPipeWireCapturer'), false); - }); -}); - -test('appendLinuxOzonePlatformHint appends ozone-platform-hint=auto on Linux', () => { - withPlatform('linux', () => { - const commandLine = createFakeCommandLine(); - appendLinuxOzonePlatformHint(commandLine); - assert.equal(commandLine.getSwitchValue('ozone-platform-hint'), 'auto'); - assert.ok(commandLine.hasSwitch('ozone-platform-hint')); - }); -}); - -test('appendLinuxOzonePlatformHint does not append on darwin or win32', () => { - withPlatform('darwin', () => { - const commandLine = createFakeCommandLine(); - appendLinuxOzonePlatformHint(commandLine); - assert.equal(commandLine.hasSwitch('ozone-platform-hint'), false); - }); - withPlatform('win32', () => { - const commandLine = createFakeCommandLine(); - appendLinuxOzonePlatformHint(commandLine); - assert.equal(commandLine.hasSwitch('ozone-platform-hint'), false); - }); -}); - -test('appendLinuxOzonePlatformHint does not override a user-supplied --ozone-platform', () => { - withPlatform('linux', () => { - const commandLine = createFakeCommandLine({'ozone-platform': 'x11'}); - assert.ok(hasConfiguredOzonePlatformSwitch(commandLine)); - appendLinuxOzonePlatformHint(commandLine); - assert.equal(commandLine.hasSwitch('ozone-platform-hint'), false); - assert.equal(commandLine.getSwitchValue('ozone-platform'), 'x11'); - }); -}); - -test('appendLinuxOzonePlatformHint respects a user-supplied bare --ozone-platform switch', () => { - withPlatform('linux', () => { - const commandLine = createFakeCommandLine({'ozone-platform': true}); - assert.ok(hasConfiguredOzonePlatformSwitch(commandLine)); - appendLinuxOzonePlatformHint(commandLine); - assert.equal(commandLine.hasSwitch('ozone-platform-hint'), false); - }); -}); - -test('resolveWaylandPortalDisplayMedia returns the first source when the portal provides one', async () => { - const source = {id: 'screen:0:0', name: 'Screen 1'} as Electron.DesktopCapturerSource; - const notifications: Array<{requestId: string; reason: string}> = []; - const streams = await resolveWaylandPortalDisplayMedia({ - requestId: 'req-1', - preference: 'monitor', - getSources: async () => [source], - notifyUnavailable: (requestId, reason) => notifications.push({requestId, reason}), - }); - assert.deepEqual(streams, {video: source}); - assert.equal(notifications.length, 0); -}); - -test('resolveWaylandPortalDisplayMedia signals an empty portal result without a video stream', async () => { - const notifications: Array<{requestId: string; reason: string}> = []; - const streams = await resolveWaylandPortalDisplayMedia({ - requestId: 'req-2', - preference: 'monitor', - getSources: async () => [], - notifyUnavailable: (requestId, reason) => notifications.push({requestId, reason}), - }); - assert.equal(streams, null); - assert.deepEqual(notifications, [{requestId: 'req-2', reason: 'empty'}]); -}); - -test('resolveWaylandPortalDisplayMedia signals a portal error when getSources rejects', async () => { - const notifications: Array<{requestId: string; reason: string}> = []; - const streams = await resolveWaylandPortalDisplayMedia({ - requestId: 'req-3', - preference: 'window', - getSources: async () => { - throw new Error('xdg-desktop-portal unavailable'); - }, - notifyUnavailable: (requestId, reason) => notifications.push({requestId, reason}), - }); - assert.equal(streams, null); - assert.deepEqual(notifications, [{requestId: 'req-3', reason: 'error'}]); -}); - -test('the Wayland portal-unavailable IPC channel matches the wired renderer channel', () => { - assert.equal(DISPLAY_MEDIA_PORTAL_EMPTY_CHANNEL, 'display-media-portal-empty'); -}); diff --git a/fluxer_desktop/src/main/WindowsVulkanGameCaptureLayer.test.ts b/fluxer_desktop/src/main/WindowsVulkanGameCaptureLayer.test.ts deleted file mode 100644 index 1c6e8c88c..000000000 --- a/fluxer_desktop/src/main/WindowsVulkanGameCaptureLayer.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-or-later - -import assert from 'node:assert/strict'; -import test from 'node:test'; - -import { - isFluxerGameCaptureVulkanLayerValue, - shouldRemoveStaleFluxerGameCaptureVulkanLayerValue, -} from './WindowsVulkanGameCaptureLayer'; - -const INSTALLED_MANIFEST_PATH = - 'C:\\Users\\hampus\\AppData\\Local\\fluxer_desktop_canary\\current\\resources\\app.asar.unpacked\\node_modules\\@fluxer\\win-game-capture\\fluxer-vulkan-layer.win32-arm64-msvc.json'; -const DEV_TREE_MANIFEST_PATH = - 'C:\\t\\fluxer\\fluxer_desktop\\native\\win-game-capture\\fluxer-vulkan-layer.win32-arm64-msvc.json'; -const RETIRED_PACKAGE_MANIFEST_PATH = - 'C:\\Users\\hampus\\AppData\\Local\\fluxer_desktop\\current\\resources\\app.asar.unpacked\\node_modules\\@fluxer\\win-screen-capture\\fluxer-vulkan-layer.win32-arm64-msvc.json'; - -test('isFluxerGameCaptureVulkanLayerValue matches the installed @fluxer/win-game-capture manifest', () => { - assert.ok(isFluxerGameCaptureVulkanLayerValue(INSTALLED_MANIFEST_PATH)); -}); - -test('isFluxerGameCaptureVulkanLayerValue matches a dev/build tree manifest outside node_modules/@fluxer', () => { - assert.ok(isFluxerGameCaptureVulkanLayerValue(DEV_TREE_MANIFEST_PATH)); -}); - -test('isFluxerGameCaptureVulkanLayerValue matches the retired win-screen-capture package name', () => { - assert.ok(isFluxerGameCaptureVulkanLayerValue(RETIRED_PACKAGE_MANIFEST_PATH)); -}); - -test('isFluxerGameCaptureVulkanLayerValue matches every supported architecture and registry slash style', () => { - for (const arch of ['x64', 'ia32', 'arm64']) { - assert.ok( - isFluxerGameCaptureVulkanLayerValue( - `C:\\t\\fluxer\\native\\win-game-capture\\fluxer-vulkan-layer.win32-${arch}-msvc.json`, - ), - arch, - ); - } - assert.ok( - isFluxerGameCaptureVulkanLayerValue( - 'C:/t/fluxer/fluxer_desktop/native/win-game-capture/Fluxer-Vulkan-Layer.win32-ARM64-msvc.json', - ), - ); -}); - -test('isFluxerGameCaptureVulkanLayerValue never matches another vendor Vulkan implicit layer', () => { - const foreignValues = [ - 'C:\\Program Files\\NVIDIA Corporation\\Nsight Graphics\\nvoglv64.json', - 'C:\\Program Files (x86)\\Steam\\steamoverlayvulkanlayer.json', - 'C:\\Program Files\\obs-studio\\data\\obs-plugins\\win-capture\\obs-vulkan64.json', - 'C:\\Windows\\System32\\VkLayer_khronos_validation.json', - 'C:\\Program Files\\OtherVendor\\layers\\fluxer-vulkan-layer.win32-x64-msvc.json', - 'C:\\t\\fluxer\\fluxer_desktop\\native\\win-game-capture\\othervendor-vulkan-layer.json', - 'C:\\t\\fluxer\\fluxer_desktop\\native\\linux-screen-capture\\fluxer-vulkan-layer.win32-x64-msvc.json', - 'C:\\t\\fluxer\\fluxer_desktop\\native\\mac-screen-capture\\fluxer-vulkan-layer.win32-x64-msvc.json', - 'C:\\t\\fluxer\\fluxer_desktop\\native\\win-game-capture\\fluxer-vulkan-layer.win32-arm64-msvc.dll', - ]; - for (const valueName of foreignValues) { - assert.equal(isFluxerGameCaptureVulkanLayerValue(valueName), false, valueName); - } -}); - -test('shouldRemoveStaleFluxerGameCaptureVulkanLayerValue keeps the live registration of the running install', () => { - assert.equal( - shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(INSTALLED_MANIFEST_PATH, INSTALLED_MANIFEST_PATH), - false, - ); - assert.equal( - shouldRemoveStaleFluxerGameCaptureVulkanLayerValue( - INSTALLED_MANIFEST_PATH.replace(/\\/g, '/').toUpperCase(), - INSTALLED_MANIFEST_PATH, - ), - false, - ); -}); - -test('shouldRemoveStaleFluxerGameCaptureVulkanLayerValue removes orphaned registrations alongside the kept one', () => { - assert.ok(shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(DEV_TREE_MANIFEST_PATH, INSTALLED_MANIFEST_PATH)); - assert.ok(shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(RETIRED_PACKAGE_MANIFEST_PATH, INSTALLED_MANIFEST_PATH)); -}); - -test('shouldRemoveStaleFluxerGameCaptureVulkanLayerValue removes every Fluxer layer when nothing is kept', () => { - for (const valueName of [INSTALLED_MANIFEST_PATH, DEV_TREE_MANIFEST_PATH, RETIRED_PACKAGE_MANIFEST_PATH]) { - assert.ok(shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(valueName, null), valueName); - } -}); - -test('shouldRemoveStaleFluxerGameCaptureVulkanLayerValue never removes a foreign vendor layer, kept path or not', () => { - const foreignValue = 'C:\\Program Files (x86)\\Steam\\steamoverlayvulkanlayer.json'; - assert.equal(shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(foreignValue, null), false); - assert.equal(shouldRemoveStaleFluxerGameCaptureVulkanLayerValue(foreignValue, INSTALLED_MANIFEST_PATH), false); -});