mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
* feat: native auto updater for MSIX on Windows * doc: added MSIX debug documentation * fix: allow downgrade with json release file and emit update-available * test: msix auot-update tests * doc: API documentation * test: add package version validation * fix: docs typo * fix: don't allow auto-updating when using appinstaller manifest * fix: getPackageInfo interface implementation * fix: review feedback, add comment * fix: missed filename commit * fix: install test cert on demand * fix: time stamp mismatch in tests * fix: feedback - rename to MSIXPackageInfo * fix: update and reference windowsStore property * fix: remove getPackagInfo from public API * fix: type error bcause of removed API
337 lines
12 KiB
TypeScript
337 lines
12 KiB
TypeScript
import { expect } from 'chai';
|
|
import * as express from 'express';
|
|
|
|
import * as http from 'node:http';
|
|
import { AddressInfo } from 'node:net';
|
|
|
|
import {
|
|
getElectronExecutable,
|
|
getMainJsFixturePath,
|
|
getMsixFixturePath,
|
|
getMsixPackageVersion,
|
|
installMsixCertificate,
|
|
installMsixPackage,
|
|
registerExecutableWithIdentity,
|
|
shouldRunMsixTests,
|
|
spawn,
|
|
uninstallMsixPackage,
|
|
unregisterExecutableWithIdentity
|
|
} from './lib/msix-helpers';
|
|
import { ifdescribe } from './lib/spec-helpers';
|
|
|
|
const ELECTRON_MSIX_ALIAS = 'ElectronMSIX.exe';
|
|
const MAIN_JS_PATH = getMainJsFixturePath();
|
|
const MSIX_V1 = getMsixFixturePath('v1');
|
|
const MSIX_V2 = getMsixFixturePath('v2');
|
|
|
|
// We can only test the MSIX updater on Windows
|
|
ifdescribe(shouldRunMsixTests)('autoUpdater MSIX behavior', function () {
|
|
this.timeout(120000);
|
|
|
|
before(async function () {
|
|
await installMsixCertificate();
|
|
|
|
const electronExec = getElectronExecutable();
|
|
await registerExecutableWithIdentity(electronExec);
|
|
});
|
|
|
|
after(async function () {
|
|
await unregisterExecutableWithIdentity();
|
|
});
|
|
|
|
const launchApp = (executablePath: string, args: string[] = []) => {
|
|
return spawn(executablePath, args);
|
|
};
|
|
|
|
const logOnError = (what: any, fn: () => void) => {
|
|
try {
|
|
fn();
|
|
} catch (err) {
|
|
console.error(what);
|
|
throw err;
|
|
}
|
|
};
|
|
|
|
it('should launch Electron via MSIX alias', async () => {
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, ['--version']);
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
});
|
|
});
|
|
|
|
it('should print package identity information', async () => {
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--printPackageId']);
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(launchResult.out).to.include('Family Name: Electron.Dev.MSIX_rdjwn13tdj8dy');
|
|
expect(launchResult.out).to.include('Package ID: Electron.Dev.MSIX_1.0.0.0_x64__rdjwn13tdj8dy');
|
|
expect(launchResult.out).to.include('Version: 1.0.0.0');
|
|
});
|
|
});
|
|
|
|
describe('with update server', () => {
|
|
let port = 0;
|
|
let server: express.Application = null as any;
|
|
let httpServer: http.Server = null as any;
|
|
let requests: express.Request[] = [];
|
|
|
|
beforeEach((done) => {
|
|
requests = [];
|
|
server = express();
|
|
server.use((req, res, next) => {
|
|
requests.push(req);
|
|
next();
|
|
});
|
|
httpServer = server.listen(0, '127.0.0.1', () => {
|
|
port = (httpServer.address() as AddressInfo).port;
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (httpServer) {
|
|
await new Promise<void>(resolve => {
|
|
httpServer.close(() => {
|
|
httpServer = null as any;
|
|
server = null as any;
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
await uninstallMsixPackage('com.electron.myapp');
|
|
});
|
|
|
|
it('should not update when no update is available', async () => {
|
|
server.get('/update-check', (req, res) => {
|
|
res.status(204).send();
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--checkUpdate', `http://localhost:${port}/update-check`]);
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update not available');
|
|
});
|
|
});
|
|
|
|
it('should hit the update endpoint with custom headers when checkForUpdates is called', async () => {
|
|
server.get('/update-check', (req, res) => {
|
|
expect(req.headers['x-appversion']).to.equal('1.0.0');
|
|
expect(req.headers.authorization).to.equal('Bearer test-token');
|
|
res.status(204).send();
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [
|
|
MAIN_JS_PATH,
|
|
'--checkUpdate',
|
|
`http://localhost:${port}/update-check`,
|
|
'--useCustomHeaders'
|
|
]);
|
|
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update not available');
|
|
});
|
|
});
|
|
|
|
it('should update successfully with direct link to MSIX file', async () => {
|
|
await installMsixPackage(MSIX_V1);
|
|
const initialVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(initialVersion).to.equal('1.0.0.0');
|
|
|
|
server.get('/update.msix', (req, res) => {
|
|
res.download(MSIX_V2);
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [
|
|
MAIN_JS_PATH,
|
|
'--checkUpdate',
|
|
`http://localhost:${port}/update.msix`
|
|
]);
|
|
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update available');
|
|
expect(launchResult.out).to.include('Update downloaded');
|
|
expect(launchResult.out).to.include('Release Name: N/A');
|
|
expect(launchResult.out).to.include('Release Notes: N/A');
|
|
expect(launchResult.out).to.include(`Update URL: http://localhost:${port}/update.msix`);
|
|
});
|
|
|
|
const updatedVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(updatedVersion).to.equal('2.0.0.0');
|
|
});
|
|
|
|
it('should update successfully with JSON response', async () => {
|
|
await installMsixPackage(MSIX_V1);
|
|
const initialVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(initialVersion).to.equal('1.0.0.0');
|
|
|
|
const fixedPubDate = '2011-11-11T11:11:11.000Z';
|
|
const expectedDateStr = new Date(fixedPubDate).toDateString();
|
|
|
|
server.get('/update-check', (req, res) => {
|
|
res.json({
|
|
url: `http://localhost:${port}/update.msix`,
|
|
name: '2.0.0',
|
|
notes: 'Test release notes',
|
|
pub_date: fixedPubDate
|
|
});
|
|
});
|
|
|
|
server.get('/update.msix', (req, res) => {
|
|
res.download(MSIX_V2);
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--checkUpdate', `http://localhost:${port}/update-check`]);
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update available');
|
|
expect(launchResult.out).to.include('Update downloaded');
|
|
expect(launchResult.out).to.include('Release Name: 2.0.0');
|
|
expect(launchResult.out).to.include('Release Notes: Test release notes');
|
|
expect(launchResult.out).to.include(`Release Date: ${expectedDateStr}`);
|
|
expect(launchResult.out).to.include(`Update URL: http://localhost:${port}/update.msix`);
|
|
});
|
|
|
|
const updatedVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(updatedVersion).to.equal('2.0.0.0');
|
|
});
|
|
|
|
it('should update successfully with static JSON releases file', async () => {
|
|
await installMsixPackage(MSIX_V1);
|
|
const initialVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(initialVersion).to.equal('1.0.0.0');
|
|
|
|
const fixedPubDate = '2011-11-11T11:11:11.000Z';
|
|
const expectedDateStr = new Date(fixedPubDate).toDateString();
|
|
|
|
server.get('/update-check', (req, res) => {
|
|
res.json({
|
|
currentRelease: '2.0.0',
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
updateTo: {
|
|
version: '1.0.0',
|
|
url: `http://localhost:${port}/update-v1.msix`,
|
|
name: '1.0.0',
|
|
notes: 'Initial release',
|
|
pub_date: '2010-10-10T10:10:10.000Z'
|
|
}
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
updateTo: {
|
|
version: '2.0.0',
|
|
url: `http://localhost:${port}/update-v2.msix`,
|
|
name: '2.0.0',
|
|
notes: 'Test release notes for static format',
|
|
pub_date: fixedPubDate
|
|
}
|
|
}
|
|
]
|
|
});
|
|
});
|
|
|
|
server.get('/update-v2.msix', (req, res) => {
|
|
res.download(MSIX_V2);
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--checkUpdate', `http://localhost:${port}/update-check`]);
|
|
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update available');
|
|
expect(launchResult.out).to.include('Update downloaded');
|
|
expect(launchResult.out).to.include('Release Name: 2.0.0');
|
|
expect(launchResult.out).to.include('Release Notes: Test release notes for static format');
|
|
expect(launchResult.out).to.include(`Release Date: ${expectedDateStr}`);
|
|
expect(launchResult.out).to.include(`Update URL: http://localhost:${port}/update-v2.msix`);
|
|
});
|
|
|
|
const updatedVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(updatedVersion).to.equal('2.0.0.0');
|
|
});
|
|
|
|
it('should not update with update File JSON Format if currentRelease is older than installed version', async () => {
|
|
await installMsixPackage(MSIX_V2);
|
|
|
|
server.get('/update-check', (req, res) => {
|
|
res.json({
|
|
currentRelease: '1.0.0',
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
updateTo: {
|
|
version: '1.0.0',
|
|
url: `http://localhost:${port}/update-v1.msix`,
|
|
name: '1.0.0',
|
|
notes: 'Initial release',
|
|
pub_date: '2010-10-10T10:10:10.000Z'
|
|
}
|
|
}
|
|
]
|
|
});
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--checkUpdate', `http://localhost:${port}/update-check`]);
|
|
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update not available');
|
|
});
|
|
});
|
|
|
|
it('should downgrade to older version with JSON server format and allowAnyVersion is true', async () => {
|
|
await installMsixPackage(MSIX_V2);
|
|
const initialVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(initialVersion).to.equal('2.0.0.0');
|
|
|
|
const fixedPubDate = '2010-10-10T10:10:10.000Z';
|
|
const expectedDateStr = new Date(fixedPubDate).toDateString();
|
|
|
|
server.get('/update-check', (req, res) => {
|
|
res.json({
|
|
url: `http://localhost:${port}/update-v1.msix`,
|
|
name: '1.0.0',
|
|
notes: 'Initial release',
|
|
pub_date: fixedPubDate
|
|
});
|
|
});
|
|
|
|
server.get('/update-v1.msix', (req, res) => {
|
|
res.download(MSIX_V1);
|
|
});
|
|
|
|
const launchResult = await launchApp(ELECTRON_MSIX_ALIAS, [MAIN_JS_PATH, '--checkUpdate', `http://localhost:${port}/update-check`, '--allowAnyVersion']);
|
|
|
|
logOnError(launchResult, () => {
|
|
expect(launchResult.code).to.equal(0);
|
|
expect(requests.length).to.be.greaterThan(0);
|
|
expect(launchResult.out).to.include('Checking for update...');
|
|
expect(launchResult.out).to.include('Update available');
|
|
expect(launchResult.out).to.include('Update downloaded');
|
|
expect(launchResult.out).to.include('Release Name: 1.0.0');
|
|
expect(launchResult.out).to.include('Release Notes: Initial release');
|
|
expect(launchResult.out).to.include(`Release Date: ${expectedDateStr}`);
|
|
expect(launchResult.out).to.include(`Update URL: http://localhost:${port}/update-v1.msix`);
|
|
});
|
|
|
|
const downgradedVersion = await getMsixPackageVersion('com.electron.myapp');
|
|
expect(downgradedVersion).to.equal('1.0.0.0');
|
|
});
|
|
});
|
|
});
|