1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Start installing updates automatically when quitting application

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-05-11 12:51:26 +03:00
parent e3579d82cb
commit 244f283998
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
6 changed files with 215 additions and 11 deletions

View File

@ -18,12 +18,14 @@ import downloadPlatformUpdateInjectable from "../../main/update-app/download-pla
import selectedUpdateChannelInjectable from "../../main/update-app/selected-update-channel.injectable";
import progressOfUpdateDownloadInjectable from "../../main/update-app/progress-of-update-download.injectable";
import type { IComputedValue } from "mobx";
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
describe("installing update using tray", () => {
let applicationBuilder: ApplicationBuilder;
let quitAndInstallUpdateMock: jest.Mock;
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
let downloadPlatformUpdateMock: AsyncFnMock<() => void>;
let setUpdateOnQuitMock: jest.Mock;
beforeEach(() => {
applicationBuilder = getApplicationBuilder();
@ -32,6 +34,9 @@ describe("installing update using tray", () => {
quitAndInstallUpdateMock = jest.fn();
checkForPlatformUpdatesMock = asyncFn();
downloadPlatformUpdateMock = asyncFn();
setUpdateOnQuitMock = jest.fn();
mainDi.override(setUpdateOnQuitInjectable, () => setUpdateOnQuitMock);
mainDi.override(
checkForPlatformUpdatesInjectable,
@ -150,7 +155,7 @@ describe("installing update using tray", () => {
await checkForUpdatesPromise;
});
it("starts downloading the update!?!?", () => {
it("starts downloading the update", () => {
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
});
@ -289,7 +294,9 @@ describe("installing update using tray", () => {
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: true });
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
@ -298,7 +305,9 @@ describe("installing update using tray", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: false });
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('checks updates from update channel "beta"', () => {
@ -310,7 +319,9 @@ describe("installing update using tray", () => {
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: true });
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
@ -319,7 +330,9 @@ describe("installing update using tray", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: false });
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('finally checks updates from update channel "latest"', () => {
@ -331,13 +344,67 @@ describe("installing update using tray", () => {
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: true });
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
});
});
});
describe('given update channel "beta" is selected', () => {
let selectedUpdateChannel: {
value: IComputedValue<UpdateChannel>;
setValue: (channelId: UpdateChannelId) => void;
};
beforeEach(() => {
selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
selectedUpdateChannelInjectable,
);
selectedUpdateChannel.setValue(updateChannels.beta.id);
});
describe("when checking for updates", () => {
beforeEach(() => {
applicationBuilder.tray.click("check-for-updates");
});
describe('when update from "beta" channel is discovered', () => {
beforeEach(async () => {
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-beta-version",
});
});
describe("when update is downloaded", () => {
beforeEach(async () => {
await downloadPlatformUpdateMock.resolve();
});
it("when user would close the application, installs the update", () => {
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true);
});
it('given user changes update channel to "latest", when user would close the application, does not install the update for not being stable enough', () => {
selectedUpdateChannel.setValue(updateChannels.latest.id);
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false);
});
it('given user changes update channel to "alpha", when user would close the application, installs the update for being stable enough', () => {
selectedUpdateChannel.setValue(updateChannels.alpha.id);
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false);
});
});
});
});
});
});
xdescribe("given a non-installed update is already downloaded, when started", () => {
@ -445,7 +512,9 @@ describe("installing update using tray", () => {
await checkForUpdatesPromise;
});
it("starts downloading the update!?!?", () => {});
it("starts downloading the update", () => {
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
});
it("user cannot check for updates again yet", () => {
expect(

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import electronUpdaterInjectable from "./electron-updater.injectable";
const setUpdateOnQuitInjectable = getInjectable({
id: "set-update-on-quit",
instantiate: (di) => {
const electronUpdater = di.inject(electronUpdaterInjectable);
return (updateOnQuit: boolean) => {
electronUpdater.autoInstallOnAppQuit = updateOnQuit;
};
},
});
export default setUpdateOnQuitInjectable;

View File

@ -22,9 +22,11 @@ const versionUpdateInjectable = getInjectable({
const discoveredVersionState = observable.box<string>();
const downloadingState = observable.box<boolean>(false);
const checkingState = observable.box<boolean>(false);
const discoveredFromUpdateChannelState = observable.box<UpdateChannel>();
return {
discoveredVersion: computed(() => discoveredVersionState.get()),
discoveredFromUpdateChannel: computed(() => discoveredFromUpdateChannelState.get()),
downloading: computed(() => downloadingState.get()),
checking: computed(() => checkingState.get()),
@ -33,6 +35,7 @@ const versionUpdateInjectable = getInjectable({
discoveredVersionState,
checkingState,
selectedUpdateChannel.value,
discoveredFromUpdateChannelState,
),
downloadUpdate: downloadUpdateFor(
@ -68,6 +71,7 @@ const checkForUpdatesFor =
discoveredVersionState: IObservableValue<string>,
checkingState: IObservableValue<boolean>,
selectedUpdateChannel: IComputedValue<UpdateChannel>,
discoveredFromUpdateChannelState: IObservableValue<UpdateChannel>,
) =>
async () => {
runInAction(() => {
@ -77,11 +81,12 @@ const checkForUpdatesFor =
const checkForUpdatesStartingFromChannel =
checkForUpdatesStartingFromChannelFor(checkForPlatformUpdates);
const { updateWasDiscovered, version } = await checkForUpdatesStartingFromChannel(
const { updateWasDiscovered, version, actualUpdateChannel } = await checkForUpdatesStartingFromChannel(
selectedUpdateChannel.get(),
);
runInAction(() => {
discoveredFromUpdateChannelState.set(actualUpdateChannel);
discoveredVersionState.set(version);
checkingState.set(false);
});
@ -90,12 +95,24 @@ const checkForUpdatesFor =
};
const checkForUpdatesStartingFromChannelFor = (checkForPlatformUpdates: CheckForPlatformUpdates) => {
const _recursiveCheck = async (updateChannel: UpdateChannel): Promise<{ updateWasDiscovered: boolean; version?: string }> => {
const checkForUpdatesStartingFromChannelFor = (
checkForPlatformUpdates: CheckForPlatformUpdates,
) => {
const _recursiveCheck = async (
updateChannel: UpdateChannel,
): Promise<{
updateWasDiscovered: boolean;
version?: string;
actualUpdateChannel?: UpdateChannel;
}> => {
const result = await checkForPlatformUpdates(updateChannel);
if (result.updateWasDiscovered) {
return { updateWasDiscovered: true, version: result.version };
return {
updateWasDiscovered: true,
version: result.version,
actualUpdateChannel: updateChannel,
};
}
if (updateChannel.moreStableUpdateChannel) {

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/on-load-of-application-injection-token";
import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable";
const startWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({
id: "start-watching-if-update-should-happen-on-quit",
instantiate: (di) => {
const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable);
return {
run: () => {
watchIfUpdateShouldHappenOnQuit.start();
},
};
},
injectionToken: onLoadOfApplicationInjectionToken,
});
export default startWatchingIfUpdateShouldHappenOnQuitInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable";
import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token";
const stopWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({
id: "stop-watching-if-update-should-happen-on-quit",
instantiate: (di) => {
const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable);
return {
run: () => {
watchIfUpdateShouldHappenOnQuit.stop();
},
};
},
injectionToken: beforeQuitOfBackEndInjectionToken,
});
export default stopWatchingIfUpdateShouldHappenOnQuitInjectable;

View File

@ -0,0 +1,48 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { autorun } from "mobx";
import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
import setUpdateOnQuitInjectable from "../../electron-app/features/set-update-on-quit.injectable";
import versionUpdateInjectable from "../version-update.injectable";
import selectedUpdateChannelInjectable from "../selected-update-channel.injectable";
import type { UpdateChannel } from "../update-channels";
const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
id: "watch-if-update-should-happen-on-quit",
instantiate: (di) => {
const setUpdateOnQuit = di.inject(setUpdateOnQuitInjectable);
const versionUpdate = di.inject(versionUpdateInjectable);
const selectedUpdateChannel = di.inject(selectedUpdateChannelInjectable);
return getStartableStoppable("watch-if-update-should-happen-on-quit", () =>
autorun(() => {
const sufficientlyStableUpdateChannels =
getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get());
const updateIsDiscoveredFromChannel = versionUpdate.discoveredFromUpdateChannel.get();
const updateOnQuit = sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel);
setUpdateOnQuit(updateOnQuit);
}),
);
},
});
const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): UpdateChannel[] => {
if (!updateChannel.moreStableUpdateChannel) {
return [updateChannel];
}
return [
updateChannel,
...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel),
];
};
export default watchIfUpdateShouldHappenOnQuitInjectable;