158 lines
5.7 KiB
JavaScript
158 lines
5.7 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const Module = require('node:module');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const packageJson = require('../package.json');
|
|
|
|
test('packages every Electron preload referenced by the main process', () => {
|
|
assert.ok(packageJson.build.files.includes('preload.js'));
|
|
assert.ok(packageJson.build.files.includes('preload-drop-target.js'));
|
|
assert.equal(packageJson.build.win.signAndEditExecutable, false);
|
|
});
|
|
|
|
test('packaged identity is exact while public artifact routing remains stable', () => {
|
|
assert.equal(packageJson.build.productName, 'Multi Hoster Uploader');
|
|
assert.equal(packageJson.build.win.executableName, 'Multi Hoster Uploader');
|
|
assert.equal(packageJson.build.nsis.artifactName, 'Multi-Hoster-Upload Setup ${version}.${ext}');
|
|
assert.equal(packageJson.build.portable.artifactName, 'Multi-Hoster-Upload ${version}.${ext}');
|
|
|
|
const source = fs.readFileSync(path.join(__dirname, '..', 'main.js'), 'utf8');
|
|
assert.match(source, /app\.setPath\('userData', path\.join\(app\.getPath\('appData'\), 'multi-hoster-uploader'\)\)/);
|
|
assert.match(source, /app\.setName\('Multi Hoster Uploader'\)/);
|
|
assert.match(source, /app\.setAppUserModelId\('com\.multihoster\.uploader'\)/);
|
|
assert.doesNotMatch(source, /updateTrayTooltip\('Multi-Hoster-Upload'\)/);
|
|
});
|
|
|
|
test('floating drop target resolves native paths through Electron webUtils', () => {
|
|
let exposedApi = null;
|
|
const nativeFile = { name: 'fixture.mkv' };
|
|
const electronMock = {
|
|
contextBridge: {
|
|
exposeInMainWorld: (_name, api) => { exposedApi = api; }
|
|
},
|
|
ipcRenderer: {
|
|
send: () => {}
|
|
},
|
|
webUtils: {
|
|
getPathForFile: file => file === nativeFile ? 'C:\\fixtures\\fixture.mkv' : ''
|
|
}
|
|
};
|
|
const originalLoad = Module._load;
|
|
const preloadPath = require.resolve('../preload-drop-target');
|
|
delete require.cache[preloadPath];
|
|
Module._load = function (request, parent, isMain) {
|
|
if (request === 'electron') return electronMock;
|
|
return originalLoad.call(this, request, parent, isMain);
|
|
};
|
|
try {
|
|
require(preloadPath);
|
|
} finally {
|
|
Module._load = originalLoad;
|
|
delete require.cache[preloadPath];
|
|
}
|
|
|
|
assert.equal(typeof exposedApi.getPathForFile, 'function');
|
|
assert.equal(exposedApi.getPathForFile(nativeFile), 'C:\\fixtures\\fixture.mkv');
|
|
});
|
|
|
|
test('afterPack brands the executable metadata shown by Windows', async () => {
|
|
let editCall = null;
|
|
const originalLoad = Module._load;
|
|
const afterPackPath = require.resolve('../scripts/afterPack.cjs');
|
|
delete require.cache[afterPackPath];
|
|
Module._load = function (request, parent, isMain) {
|
|
if (request === 'rcedit') {
|
|
return async (exePath, options) => { editCall = { exePath, options }; };
|
|
}
|
|
return originalLoad.call(this, request, parent, isMain);
|
|
};
|
|
try {
|
|
const afterPack = require(afterPackPath);
|
|
await afterPack({
|
|
appOutDir: 'C:\\release',
|
|
packager: { appInfo: { productFilename: 'Multi Hoster Uploader', version: '9.8.7' } }
|
|
});
|
|
} finally {
|
|
Module._load = originalLoad;
|
|
delete require.cache[afterPackPath];
|
|
}
|
|
|
|
assert.equal(editCall.exePath, path.join('C:\\release', 'Multi Hoster Uploader.exe'));
|
|
assert.equal(editCall.options['file-version'], '9.8.7');
|
|
assert.equal(editCall.options['product-version'], '9.8.7');
|
|
assert.deepEqual(editCall.options['version-string'], {
|
|
CompanyName: 'Sucukdeluxe',
|
|
FileDescription: 'Multi Hoster Uploader',
|
|
InternalName: 'Multi Hoster Uploader',
|
|
OriginalFilename: 'Multi Hoster Uploader.exe',
|
|
ProductName: 'Multi Hoster Uploader'
|
|
});
|
|
});
|
|
|
|
test('afterPack fails the build when executable branding fails', async () => {
|
|
const originalLoad = Module._load;
|
|
const afterPackPath = require.resolve('../scripts/afterPack.cjs');
|
|
delete require.cache[afterPackPath];
|
|
Module._load = function (request, parent, isMain) {
|
|
if (request === 'rcedit') return async () => { throw new Error('branding failed'); };
|
|
return originalLoad.call(this, request, parent, isMain);
|
|
};
|
|
try {
|
|
const afterPack = require(afterPackPath);
|
|
await assert.rejects(afterPack({
|
|
appOutDir: 'C:\\release',
|
|
packager: { appInfo: { productFilename: 'Multi Hoster Uploader', version: '9.8.7' } }
|
|
}), /branding failed/);
|
|
} finally {
|
|
Module._load = originalLoad;
|
|
delete require.cache[afterPackPath];
|
|
}
|
|
});
|
|
|
|
test('close readiness is signaled only after the renderer explicitly finishes initialization', () => {
|
|
const listeners = new Map();
|
|
const sent = [];
|
|
let exposedApi = null;
|
|
const electronMock = {
|
|
contextBridge: {
|
|
exposeInMainWorld: (_name, api) => { exposedApi = api; }
|
|
},
|
|
ipcRenderer: {
|
|
invoke: () => Promise.resolve(),
|
|
on: (channel, listener) => { listeners.set(channel, listener); },
|
|
send: (...args) => { sent.push(args); },
|
|
removeAllListeners: () => {}
|
|
},
|
|
webUtils: {
|
|
getPathForFile: () => ''
|
|
}
|
|
};
|
|
const originalLoad = Module._load;
|
|
const preloadPath = require.resolve('../preload');
|
|
delete require.cache[preloadPath];
|
|
Module._load = function (request, parent, isMain) {
|
|
if (request === 'electron') return electronMock;
|
|
return originalLoad.call(this, request, parent, isMain);
|
|
};
|
|
try {
|
|
require(preloadPath);
|
|
} finally {
|
|
Module._load = originalLoad;
|
|
}
|
|
|
|
let closeAttempt = null;
|
|
exposedApi.onPrepareClose(attempt => { closeAttempt = attempt; });
|
|
assert.deepEqual(sent, []);
|
|
|
|
listeners.get('app:prepare-close')({}, 7);
|
|
assert.equal(closeAttempt, 7);
|
|
assert.deepEqual(sent, [['app:close-preparation-started', 7]]);
|
|
|
|
exposedApi.signalCloseHandshakeReady();
|
|
assert.deepEqual(sent, [
|
|
['app:close-preparation-started', 7],
|
|
['app:close-handshake-ready']
|
|
]);
|
|
});
|