feat(macos): configuration window + curl-backed macOS updater (#71)

This commit is contained in:
2026-05-17 02:23:44 -07:00
committed by GitHub
parent 6ca5cede3e
commit e84674e3b5
100 changed files with 13890 additions and 235 deletions
+66 -5
View File
@@ -151,11 +151,72 @@ test('manual update check does not prompt restart when only launcher updates', a
const result = await service.checkForUpdates({ source: 'manual' });
assert.equal(result.status, 'update-available');
assert.deepEqual(calls, [
'available-dialog:0.15.0',
'launcher:stable',
'manual-install:0.15.0',
]);
assert.deepEqual(calls, ['available-dialog:0.15.0', 'launcher:stable', 'manual-install:0.15.0']);
});
test('manual update check can skip release metadata after unsupported app updater', async () => {
const { deps, calls } = createDeps({
checkAppUpdate: async () => ({ available: false, version: '0.14.0', canUpdate: false }),
shouldFetchReleaseMetadata: ({ appUpdate }) => appUpdate.canUpdate !== false,
fetchLatestStableRelease: async () => {
calls.push('fetch-release');
return {
tag_name: 'v0.15.0',
prerelease: false,
draft: false,
assets: [],
};
},
} as Partial<UpdateServiceDeps>);
const service = createUpdateService(deps);
const result = await service.checkForUpdates({ source: 'manual' });
assert.equal(result.status, 'up-to-date');
assert.deepEqual(calls, ['no-update:0.14.0']);
});
test('manual update check fetches release metadata after app metadata errors', async () => {
const { deps, calls } = createDeps({
checkAppUpdate: async () => {
throw new Error('latest-mac.yml missing');
},
shouldFetchReleaseMetadata: ({ appUpdate }) => appUpdate.canUpdate !== false,
fetchLatestStableRelease: async () => {
calls.push('fetch-release');
return {
tag_name: 'v0.15.0',
prerelease: false,
draft: false,
assets: [],
};
},
} as Partial<UpdateServiceDeps>);
const service = createUpdateService(deps);
const result = await service.checkForUpdates({ source: 'manual' });
assert.equal(result.status, 'update-available');
assert.deepEqual(calls, ['fetch-release', 'available-dialog:0.15.0']);
});
test('manual update check reports non-Error failures safely', async () => {
const { deps, calls } = createDeps({
checkAppUpdate: async () => ({ available: true, version: '0.15.0' }),
showUpdateAvailableDialog: async (version) => {
calls.push(`available-dialog:${version}`);
return 'update';
},
downloadAppUpdate: async () => {
throw 'download rejected';
},
});
const service = createUpdateService(deps);
const result = await service.checkForUpdates({ source: 'manual' });
assert.deepEqual(result, { status: 'failed', error: 'download rejected' });
assert.deepEqual(calls, ['available-dialog:0.15.0', 'failed:download rejected']);
});
test('automatic update check skips inside configured interval', async () => {