Files
openchamber/packages/electron/linux-app-discovery.test.mjs
T
ouyangjian28 bf4262dbc9 fix(desktop): keep non-ASCII desktop entries out of Open In matching (#3403)
desktopEntryMatchesApp normalized haystack values without dropping empty
ones, so a .desktop entry with no ASCII letters or digits in Name, id,
file name, or Exec (e.g. Name=抖音) normalized to "" and
needle.includes("") matched every requested app — hijacking the
installed-apps list and Open In launch specs. Empty normalized haystack
values are now filtered, matching the existing needles handling.

discovered-apps.json gains a version field (INSTALLED_APPS_CACHE_VERSION
= 2); caches written before the fix are treated as stale and refresh
through the existing TTL-expiry path instead of serving the poisoned
list for the rest of the 24h TTL.
2026-09-07 20:25:30 +03:00

88 lines
2.7 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildLinuxOpenSpecs,
filterLinuxInstalledApps,
parseDesktopEntry,
} from './linux-app-discovery.mjs';
const NON_ASCII_ONLY_ENTRY = `[Desktop Entry]
Type=Application
Name=抖音
Exec=/usr/bin/example --app-url=https://www.douyin.com/
Icon=example`;
const TEST_ENV = { PATH: '/nonexistent-openchamber-test-bin' };
const parseEntryAt = (content, id) => parseDesktopEntry(content, `/usr/share/applications/${id}.desktop`);
test('still parses desktop entries whose Name has no ASCII letters or digits', () => {
const entry = parseEntryAt(NON_ASCII_ONLY_ENTRY, 'example');
assert.ok(entry);
assert.equal(entry.name, '抖音');
assert.equal(entry.exec, '/usr/bin/example --app-url=https://www.douyin.com/');
});
test('a non-ASCII-only desktop entry does not mark every app as installed', async () => {
const entry = parseEntryAt(NON_ASCII_ONLY_ENTRY, 'example');
const installed = await filterLinuxInstalledApps(
['Visual Studio Code', 'Cursor', 'Sublime Text'],
{ entries: [entry] },
);
assert.deepEqual(installed, []);
});
test('Open In specs never launch a non-ASCII-only entry for another app', () => {
const entry = parseEntryAt(NON_ASCII_ONLY_ENTRY, 'example');
const specs = buildLinuxOpenSpecs({
targetPath: '/tmp/project',
appId: 'vscode',
appName: 'Visual Studio Code',
entries: [entry],
env: TEST_ENV,
});
assert.deepEqual(specs, []);
});
test('ASCII desktop entries still match their own app and build their own launch spec', async () => {
const entry = parseEntryAt(`[Desktop Entry]
Type=Application
Name=Visual Studio Code
Exec=/usr/bin/code %F
Icon=code`, 'code');
const installed = await filterLinuxInstalledApps(
['Visual Studio Code', 'Cursor'],
{ entries: [entry] },
);
assert.deepEqual(installed, ['Visual Studio Code']);
const specs = buildLinuxOpenSpecs({
targetPath: '/tmp/project',
appId: 'vscode',
appName: 'Visual Studio Code',
entries: [entry],
env: TEST_ENV,
});
assert.equal(specs.length, 1);
assert.equal(specs[0].program, '/usr/bin/code');
assert.deepEqual(specs[0].args, ['/tmp/project']);
});
test('entries mixing ASCII and non-ASCII still match through their ASCII part', () => {
const entry = parseEntryAt(`[Desktop Entry]
Type=Application
Name=VSCode 抖音版
Exec=/usr/local/bin/vscode-douyin %F
Icon=vscode-douyin`, 'vscode-douyin');
const specs = buildLinuxOpenSpecs({
targetPath: '/tmp/project',
appId: 'vscode',
appName: 'Visual Studio Code',
entries: [entry],
env: TEST_ENV,
});
assert.equal(specs.length, 1);
assert.equal(specs[0].program, '/usr/local/bin/vscode-douyin');
});