From eb8d316eeaa5286bc146b7d83ae2d9517f53839b Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Fri, 20 May 2022 09:56:11 +0300 Subject: [PATCH] Switch to using release channel of installed application version as default value for selected update channel Signed-off-by: Janne Savolainen --- ...g-update-from-update-channels.test.ts.snap | 8 +- ...alling-update-from-update-channels.test.ts | 88 ++++++++++++++++++- .../default-update-channel.injectable.ts | 27 ++++++ .../selected-update-channel.injectable.ts | 28 ++---- 4 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 src/common/application-update/selected-update-channel/default-update-channel.injectable.ts diff --git a/src/behaviours/update-app/__snapshots__/installing-update-from-update-channels.test.ts.snap b/src/behaviours/update-app/__snapshots__/installing-update-from-update-channels.test.ts.snap index d7fbf033d1..87df586d63 100644 --- a/src/behaviours/update-app/__snapshots__/installing-update-from-update-channels.test.ts.snap +++ b/src/behaviours/update-app/__snapshots__/installing-update-from-update-channels.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`installing update from update channels when started renders 1`] = ` +exports[`installing update from update channels given no update channel selection is stored, when started renders 1`] = `
`; -exports[`installing update from update channels when started when user checks for updates renders 1`] = ` +exports[`installing update from update channels given no update channel selection is stored, when started when user checks for updates renders 1`] = `
`; -exports[`installing update from update channels when started when user checks for updates when new update is discovered renders 1`] = ` +exports[`installing update from update channels given no update channel selection is stored, when started when user checks for updates when new update is discovered renders 1`] = `
`; -exports[`installing update from update channels when started when user checks for updates when new update is discovered when download succeeds renders 1`] = ` +exports[`installing update from update channels given no update channel selection is stored, when started when user checks for updates when new update is discovered when download succeeds renders 1`] = `
{ let applicationBuilder: ApplicationBuilder; @@ -69,7 +71,7 @@ describe("installing update from update channels", () => { }); }); - describe("when started", () => { + describe("given no update channel selection is stored, when started", () => { let rendered: RenderResult; let checkForUpdates: () => Promise; @@ -299,4 +301,88 @@ describe("installing update from update channels", () => { }); }); }); + + it("given valid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => { + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + // TODO: Switch to more natural way of setting initial value + // TODO: UserStore is currently responsible for getting and setting initial value + const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable); + + selectedUpdateChannel.setValue(updateChannels.beta.id); + }); + + await applicationBuilder.render(); + + const checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable); + + checkForUpdates(); + + expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.beta, expect.any(Object)); + }); + + it("given invalid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => { + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + // TODO: Switch to more natural way of setting initial value + // TODO: UserStore is currently responsible for getting and setting initial value + const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable); + + selectedUpdateChannel.setValue("something-invalid" as UpdateChannelId); + }); + + await applicationBuilder.render(); + + const checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable); + + checkForUpdates(); + + expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.latest, expect.any(Object)); + }); + + it('given no update channel selection is stored and currently using alpha release, when checking for updates, checks for updates from "alpha" channel', async () => { + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + mainDi.override(appVersionInjectable, () => "1.0.0-alpha"); + }); + + await applicationBuilder.render(); + + const checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable); + + checkForUpdates(); + + expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.alpha, expect.any(Object)); + }); + + it('given no update channel selection is stored and currently using beta release, when checking for updates, checks for updates from "beta" channel', async () => { + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + mainDi.override(appVersionInjectable, () => "1.0.0-beta"); + }); + + await applicationBuilder.render(); + + const checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable); + + checkForUpdates(); + + expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.beta, expect.any(Object)); + }); + + it("given update channel selection is stored and currently using prerelease, when checking for updates, checks for updates from stored channel", async () => { + applicationBuilder.beforeApplicationStart(({ mainDi }) => { + mainDi.override(appVersionInjectable, () => "1.0.0-alpha"); + + // TODO: Switch to more natural way of setting initial value + // TODO: UserStore is currently responsible for getting and setting initial value + const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable); + + selectedUpdateChannel.setValue(updateChannels.beta.id); + }); + + await applicationBuilder.render(); + + const checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable); + + checkForUpdates(); + + expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.beta, expect.any(Object)); + }); }); diff --git a/src/common/application-update/selected-update-channel/default-update-channel.injectable.ts b/src/common/application-update/selected-update-channel/default-update-channel.injectable.ts new file mode 100644 index 0000000000..3d9101b672 --- /dev/null +++ b/src/common/application-update/selected-update-channel/default-update-channel.injectable.ts @@ -0,0 +1,27 @@ +/** + * 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 { SemVer } from "semver"; +import appVersionInjectable from "../../get-configuration-file-model/app-version/app-version.injectable"; +import type { UpdateChannelId } from "../update-channels"; +import { updateChannels } from "../update-channels"; + +const defaultUpdateChannelInjectable = getInjectable({ + id: "default-update-channel", + + instantiate: (di) => { + const appVersion = di.inject(appVersionInjectable); + + const currentReleaseChannel = new SemVer(appVersion).prerelease[0]?.toString() as UpdateChannelId; + + if (currentReleaseChannel && updateChannels[currentReleaseChannel]) { + return updateChannels[currentReleaseChannel]; + } + + return updateChannels.latest; + }, +}); + +export default defaultUpdateChannelInjectable; diff --git a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts index 69370d76c6..ceb47aee5e 100644 --- a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts +++ b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts @@ -7,40 +7,28 @@ import type { IComputedValue } from "mobx"; import { action, computed, observable } from "mobx"; import type { UpdateChannel, UpdateChannelId } from "../update-channels"; import { updateChannels } from "../update-channels"; +import defaultUpdateChannelInjectable from "./default-update-channel.injectable"; export interface SelectedUpdateChannel { value: IComputedValue; setValue: (channelId?: UpdateChannelId) => void; } -// export const defaultUpdateChannel = new SemVer(getAppVersion()).prerelease[0]?.toString() || "latest"; - -// const updateChannel: PreferenceDescription = { -// fromStore(val) { -// return !val || !updateChannels.has(val) -// ? defaultUpdateChannel -// : val; -// }, -// toStore(val) { -// if (!updateChannels.has(val) || val === defaultUpdateChannel) { -// return undefined; -// } -// -// return val; -// }, -// }; - const selectedUpdateChannelInjectable = getInjectable({ id: "selected-update-channel", - instantiate: (): SelectedUpdateChannel => { - const state = observable.box(updateChannels.latest); + instantiate: (di): SelectedUpdateChannel => { + const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); + const state = observable.box(defaultUpdateChannel); return { value: computed(() => state.get()), setValue: action((channelId) => { - const targetUpdateChannel = channelId ? updateChannels[channelId] : updateChannels.latest; + const targetUpdateChannel = + channelId && updateChannels[channelId] + ? updateChannels[channelId] + : defaultUpdateChannel; state.set(targetUpdateChannel); }),