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

Reorganize tests for installing update under separate scenarios

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-05-19 13:49:33 +03:00
parent 129f9c1953
commit db60d1dace
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
4 changed files with 956 additions and 325 deletions

View File

@ -15,7 +15,48 @@ exports[`installing update using tray given no update is already downloaded, and
<div>
<div
class="Notifications flex column align-flex-end"
/>
>
<div
class="Animate opacity notification flex info"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Checking for updates...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_13"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
</div>
</div>
</body>
`;
@ -25,7 +66,88 @@ exports[`installing update using tray given no update is already downloaded, and
<div>
<div
class="Notifications flex column align-flex-end"
/>
>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Checking for updates...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_96"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Download for version some-version started...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_99"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
</div>
</div>
</body>
`;
@ -35,7 +157,128 @@ exports[`installing update using tray given no update is already downloaded, and
<div>
<div
class="Notifications flex column align-flex-end"
/>
>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Checking for updates...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_149"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Download for version some-version started...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_152"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Download of update failed
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_157"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
</div>
</div>
</body>
`;
@ -45,37 +288,156 @@ exports[`installing update using tray given no update is already downloaded, and
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update using tray given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates using tray when new update is discovered when download succeeds when user answers not to install the update renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update using tray given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates using tray when new update is discovered when download succeeds when user answers to install the update renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update using tray given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates using tray when new update is discovered when download succeeds when user disregards the question and installs the update using tray renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Checking for updates...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_215"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Download for version some-version started...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_218"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
<div
class="flex column gaps"
data-testid="ask-boolean-install-update"
>
<b>
Update Available
</b>
<p>
Version some-version of Lens IDE is available and ready to be installed. Would you like to update now?
</p>
<div
class="flex gaps row align-left box grow"
>
<button
class="Button light"
data-testid="ask-boolean-install-update-button-yes"
type="button"
>
Yes
</button>
<button
class="Button active outlined"
data-testid="ask-boolean-install-update-button-no"
type="button"
>
No
</button>
</div>
</div>
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-ask-boolean-for-install-update"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
</div>
</div>
</body>
`;
@ -85,7 +447,88 @@ exports[`installing update using tray given no update is already downloaded, and
<div>
<div
class="Notifications flex column align-flex-end"
/>
>
<div
class="Animate opacity notification flex info"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
Checking for updates...
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_48"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
<div
class="Animate opacity notification flex info"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<i
class="Icon material focusable"
>
<span
class="icon"
data-icon-name="info_outline"
>
info_outline
</span>
</i>
</div>
<div
class="message box grow"
>
No new updates available
</div>
<div
class="box"
>
<i
class="Icon close material interactive focusable"
data-testid="close-notification-for-notification_51"
tabindex="0"
>
<span
class="icon"
data-icon-name="close"
>
close
</span>
</i>
</div>
</div>
</div>
</div>
</body>
`;

View File

@ -0,0 +1,81 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when new update is discovered renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when new update is discovered when download fails renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when new update is discovered when download succeeds renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when new update is discovered when download succeeds when user answers not to install the update renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when new update is discovered when download succeeds when user answers to install the update renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`installing update given no update is already downloaded, and "latest" update channel is selected, when started when user checks for updates when no new update is discovered renders 1`] = `
<body>
<div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;

View File

@ -4,7 +4,6 @@
*/
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import quitAndInstallUpdateInjectable from "../../main/electron-app/features/quit-and-install-update.injectable";
import type { RenderResult } from "@testing-library/react";
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
import publishIsConfiguredInjectable from "../../main/update-app/publish-is-configured.injectable";
@ -12,46 +11,26 @@ import type { CheckForPlatformUpdates } from "../../main/update-app/check-for-pl
import checkForPlatformUpdatesInjectable from "../../main/update-app/check-for-platform-updates/check-for-platform-updates.injectable";
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { UpdateChannel, UpdateChannelId } from "../../main/update-app/update-channels";
import { updateChannels } from "../../main/update-app/update-channels";
import type { DownloadPlatformUpdate } from "../../main/update-app/download-platform-update/download-platform-update.injectable";
import downloadPlatformUpdateInjectable from "../../main/update-app/download-platform-update/download-platform-update.injectable";
import selectedUpdateChannelInjectable from "../../main/update-app/selected-update-channel.injectable";
import type { IComputedValue } from "mobx";
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
import showApplicationWindowInjectable from "../../main/start-main-application/lens-window/show-application-window.injectable";
import type { AskBoolean } from "../../main/ask-boolean/ask-boolean.injectable";
import askBooleanInjectable from "../../main/ask-boolean/ask-boolean.injectable";
import progressOfUpdateDownloadInjectable from "../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable";
describe("installing update using tray", () => {
let applicationBuilder: ApplicationBuilder;
let quitAndInstallUpdateMock: jest.Mock;
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
let setUpdateOnQuitMock: jest.Mock;
let showApplicationWindowMock: jest.Mock;
let showInfoNotificationMock: jest.Mock;
let askBooleanMock: AsyncFnMock<AskBoolean>;
beforeEach(() => {
applicationBuilder = getApplicationBuilder();
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
quitAndInstallUpdateMock = jest.fn();
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
checkForPlatformUpdatesMock = asyncFn();
downloadPlatformUpdateMock = asyncFn();
setUpdateOnQuitMock = jest.fn();
showApplicationWindowMock = jest.fn();
showInfoNotificationMock = jest.fn(() => () => {});
askBooleanMock = asyncFn();
rendererDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock);
mainDi.override(askBooleanInjectable, () => askBooleanMock);
mainDi.override(showApplicationWindowInjectable, () => showApplicationWindowMock);
mainDi.override(setUpdateOnQuitInjectable, () => setUpdateOnQuitMock);
mainDi.override(
checkForPlatformUpdatesInjectable,
@ -63,11 +42,6 @@ describe("installing update using tray", () => {
() => downloadPlatformUpdateMock,
);
mainDi.override(
quitAndInstallUpdateInjectable,
() => quitAndInstallUpdateMock,
);
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
mainDi.override(publishIsConfiguredInjectable, () => true);
});
@ -96,20 +70,10 @@ describe("installing update using tray", () => {
applicationBuilder.tray.click("check-for-updates");
});
it('checks for updates from "latest" update channel', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.latest,
);
});
it("does not show application window yet", () => {
expect(showApplicationWindowMock).not.toHaveBeenCalled();
});
it("notifies the user that checking for updates is happening", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Checking for updates...");
});
it("user cannot check for updates again", () => {
expect(
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
@ -132,8 +96,6 @@ describe("installing update using tray", () => {
describe("when no new update is discovered", () => {
beforeEach(async () => {
showInfoNotificationMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
@ -145,14 +107,6 @@ describe("installing update using tray", () => {
expect(showApplicationWindowMock).toHaveBeenCalled();
});
it("notifies the user", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("No new updates available");
});
it("does not start downloading update", () => {
expect(downloadPlatformUpdateMock).not.toHaveBeenCalled();
});
it("user cannot install update", () => {
expect(applicationBuilder.tray.get("install-update")).toBeUndefined();
});
@ -188,14 +142,6 @@ describe("installing update using tray", () => {
expect(showApplicationWindowMock).toHaveBeenCalled();
});
it("starts downloading the update", () => {
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
});
it("notifies the user that download is happening", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Download for version some-version started...");
});
it("user cannot check for updates again yet", () => {
expect(
applicationBuilder.tray.get("check-for-updates")?.enabled.get(),
@ -233,10 +179,6 @@ describe("installing update using tray", () => {
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false });
});
it("does not quit and install update yet", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
it("user cannot install update", () => {
expect(
applicationBuilder.tray.get("install-update"),
@ -249,20 +191,12 @@ describe("installing update using tray", () => {
).toBe(true);
});
it("notifies the user about failed download", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Download of update failed");
});
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
expect(
applicationBuilder.tray.get("check-for-updates")?.label?.get(),
).toBe("Check for updates");
});
it("does not ask user to install update", () => {
expect(askBooleanMock).not.toHaveBeenCalled();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
@ -273,10 +207,6 @@ describe("installing update using tray", () => {
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
});
it("does not quit and install update yet", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
it("user can install update", () => {
expect(
applicationBuilder.tray.get("install-update")?.label?.get(),
@ -298,225 +228,6 @@ describe("installing update using tray", () => {
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("asks user to install update immediately", () => {
expect(askBooleanMock).toHaveBeenCalledWith({
id: "install-update",
title: "Update Available",
question:
"Version some-version of Lens IDE is available and ready to be installed. Would you like to update now?",
});
});
describe("when user answers to install the update", () => {
beforeEach(async () => {
await askBooleanMock.resolve(true);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("quits application and installs the update", () => {
expect(quitAndInstallUpdateMock).toHaveBeenCalled();
});
});
describe("when user answers not to install the update", () => {
beforeEach(async () => {
await askBooleanMock.resolve(false);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not quit application and install the update", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
});
describe("when user disregards the question and installs the update using tray", () => {
beforeEach(async () => {
await applicationBuilder.tray.click("install-update");
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("quits application and installs the update", () => {
expect(quitAndInstallUpdateMock).toHaveBeenCalled();
});
});
});
describe("when user changes update channel to other channel instead of just installing", () => {
beforeEach(() => {
const selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
selectedUpdateChannelInjectable,
);
selectedUpdateChannel.setValue(updateChannels.beta.id);
});
it("user cannot install existing update for being from wrong update channel", () => {});
describe("when user installs an update", () => {
beforeEach(() => {});
it('still installs the update from "latest" update channel', () => {});
});
it("when checking updates again, checks for updates from the other update channel", async () => {
checkForPlatformUpdatesMock.mockClear();
applicationBuilder.tray.click("check-for-updates");
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.beta,
);
});
});
});
});
describe('given update channel "alpha" is selected, when checking for updates', () => {
let selectedUpdateChannel: {
value: IComputedValue<UpdateChannel>;
setValue: (channelId: UpdateChannelId) => void;
};
beforeEach(() => {
selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
selectedUpdateChannelInjectable,
);
selectedUpdateChannel.setValue(updateChannels.alpha.id);
applicationBuilder.tray.click("check-for-updates");
});
it('checks updates from update channel "alpha"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.alpha,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
describe("when no update is discovered", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('checks updates from update channel "beta"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.beta,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
describe("when no update is discovered again", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('finally checks updates from update channel "latest"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.latest,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
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({ downloadWasSuccessful: true });
});
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);
});
});
});
});
});

View File

@ -0,0 +1,396 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import quitAndInstallUpdateInjectable from "../../main/electron-app/features/quit-and-install-update.injectable";
import type { RenderResult } from "@testing-library/react";
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
import publishIsConfiguredInjectable from "../../main/update-app/publish-is-configured.injectable";
import type { CheckForPlatformUpdates } from "../../main/update-app/check-for-platform-updates/check-for-platform-updates.injectable";
import checkForPlatformUpdatesInjectable from "../../main/update-app/check-for-platform-updates/check-for-platform-updates.injectable";
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { UpdateChannel, UpdateChannelId } from "../../main/update-app/update-channels";
import { updateChannels } from "../../main/update-app/update-channels";
import type { DownloadPlatformUpdate } from "../../main/update-app/download-platform-update/download-platform-update.injectable";
import downloadPlatformUpdateInjectable from "../../main/update-app/download-platform-update/download-platform-update.injectable";
import selectedUpdateChannelInjectable from "../../main/update-app/selected-update-channel.injectable";
import type { IComputedValue } from "mobx";
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
import type { AskBoolean } from "../../main/ask-boolean/ask-boolean.injectable";
import askBooleanInjectable from "../../main/ask-boolean/ask-boolean.injectable";
import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable";
import checkForUpdatesInjectable from "../../main/update-app/check-for-updates/check-for-updates.injectable";
describe("installing update", () => {
let applicationBuilder: ApplicationBuilder;
let quitAndInstallUpdateMock: jest.Mock;
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
let setUpdateOnQuitMock: jest.Mock;
let showInfoNotificationMock: jest.Mock;
let askBooleanMock: AsyncFnMock<AskBoolean>;
beforeEach(() => {
applicationBuilder = getApplicationBuilder();
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
quitAndInstallUpdateMock = jest.fn();
checkForPlatformUpdatesMock = asyncFn();
downloadPlatformUpdateMock = asyncFn();
setUpdateOnQuitMock = jest.fn();
showInfoNotificationMock = jest.fn(() => () => {});
askBooleanMock = asyncFn();
rendererDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock);
mainDi.override(askBooleanInjectable, () => askBooleanMock);
mainDi.override(setUpdateOnQuitInjectable, () => setUpdateOnQuitMock);
mainDi.override(
checkForPlatformUpdatesInjectable,
() => checkForPlatformUpdatesMock,
);
mainDi.override(
downloadPlatformUpdateInjectable,
() => downloadPlatformUpdateMock,
);
mainDi.override(
quitAndInstallUpdateInjectable,
() => quitAndInstallUpdateMock,
);
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
mainDi.override(publishIsConfiguredInjectable, () => true);
});
});
describe('given no update is already downloaded, and "latest" update channel is selected, when started', () => {
let rendered: RenderResult;
let checkForUpdates: () => Promise<void>;
beforeEach(async () => {
rendered = await applicationBuilder.render();
checkForUpdates = applicationBuilder.dis.mainDi.inject(checkForUpdatesInjectable);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
describe("when user checks for updates", () => {
let checkForUpdatesPromise: Promise<void>;
beforeEach(async () => {
checkForUpdatesPromise = checkForUpdates();
});
it('checks for updates from "latest" update channel', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.latest,
);
});
it("notifies the user that checking for updates is happening", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Checking for updates...");
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
describe("when no new update is discovered", () => {
beforeEach(async () => {
showInfoNotificationMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
await checkForUpdatesPromise;
});
it("notifies the user", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("No new updates available");
});
it("does not start downloading update", () => {
expect(downloadPlatformUpdateMock).not.toHaveBeenCalled();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
});
describe("when new update is discovered", () => {
beforeEach(async () => {
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
await checkForUpdatesPromise;
});
it("starts downloading the update", () => {
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
});
it("notifies the user that download is happening", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Download for version some-version started...");
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
describe("when download fails", () => {
beforeEach(async () => {
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false });
});
it("does not quit and install update yet", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
it("notifies the user about failed download", () => {
expect(showInfoNotificationMock).toHaveBeenCalledWith("Download of update failed");
});
it("does not ask user to install update", () => {
expect(askBooleanMock).not.toHaveBeenCalled();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
});
describe("when download succeeds", () => {
beforeEach(async () => {
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
});
it("does not quit and install update yet", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("asks user to install update immediately", () => {
expect(askBooleanMock).toHaveBeenCalledWith({
id: "install-update",
title: "Update Available",
question:
"Version some-version of Lens IDE is available and ready to be installed. Would you like to update now?",
});
});
describe("when user answers to install the update", () => {
beforeEach(async () => {
await askBooleanMock.resolve(true);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("quits application and installs the update", () => {
expect(quitAndInstallUpdateMock).toHaveBeenCalled();
});
});
describe("when user answers not to install the update", () => {
beforeEach(async () => {
await askBooleanMock.resolve(false);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not quit application and install the update", () => {
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
});
});
describe("when user changes update channel to other channel instead of just installing", () => {
beforeEach(() => {
const selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
selectedUpdateChannelInjectable,
);
selectedUpdateChannel.setValue(updateChannels.beta.id);
});
it("user cannot install existing update for being from wrong update channel", () => {});
describe("when user installs an update", () => {
beforeEach(() => {});
it('still installs the update from "latest" update channel', () => {});
});
it("when checking updates again, checks for updates from the other update channel", async () => {
checkForPlatformUpdatesMock.mockClear();
checkForUpdates();
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.beta,
);
});
});
});
});
describe('given update channel "alpha" is selected, when checking for updates', () => {
let selectedUpdateChannel: {
value: IComputedValue<UpdateChannel>;
setValue: (channelId: UpdateChannelId) => void;
};
beforeEach(() => {
selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
selectedUpdateChannelInjectable,
);
selectedUpdateChannel.setValue(updateChannels.alpha.id);
checkForUpdates();
});
it('checks updates from update channel "alpha"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.alpha,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
describe("when no update is discovered", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('checks updates from update channel "beta"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.beta,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
expect(checkForPlatformUpdatesMock).not.toHaveBeenCalled();
});
describe("when no update is discovered again", () => {
beforeEach(async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: false,
});
});
it('finally checks updates from update channel "latest"', () => {
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
updateChannels.latest,
);
});
it("when update is discovered, does not check update from other update channels", async () => {
checkForPlatformUpdatesMock.mockClear();
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "some-version",
});
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(() => {
checkForUpdates();
});
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({ downloadWasSuccessful: true });
});
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);
});
});
});
});
});
});
});