Force update after thirty days since update was downloaded (#5776)

This commit is contained in:
Janne Savolainen authored and GitHub committed 2022-07-06 09:48:00 -04:00
1 parent eb6cc70143
commit 6e5c8e0427
12 files changed
+1280

No files matched your search

@@ -0,0 +1,708 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`force user to update when too long since update was downloaded when application is started given checking for updates and it resolves, when update was downloaded renders 1`] = `
<body>
<div>
<div
class="ClusterManager"
>
<div
class="topBar"
>
<div
class="items"
>
<i
class="Icon material interactive focusable"
data-testid="home-button"
tabindex="0"
>
<span
class="icon"
data-icon-name="home"
>
home
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-back"
>
<span
class="icon"
data-icon-name="arrow_back"
>
arrow_back
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-forward"
>
<span
class="icon"
data-icon-name="arrow_forward"
>
arrow_forward
</span>
</i>
<button
class="updateButton"
data-testid="update-button"
data-warning-level="light"
id="update-lens-button"
>
Update
<i
class="Icon icon material focusable"
>
<span
class="icon"
data-icon-name="arrow_drop_down"
>
arrow_drop_down
</span>
</i>
</button>
</div>
<div
class="items"
/>
</div>
<main>
<div
id="lens-views"
/>
<div
class="flex justify-center Welcome align-center"
data-testid="welcome-page"
>
<div
data-testid="welcome-banner-container"
style="width: 320px;"
>
<i
class="Icon logo svg focusable"
>
<span
class="icon"
/>
</i>
<div
class="flex justify-center"
>
<div
data-testid="welcome-text-container"
style="width: 320px;"
>
<h2>
Welcome to OpenLens 5!
</h2>
<p>
To get you started we have auto-detected your clusters in your
kubeconfig file and added them to the catalog, your centralized
view for managing all your cloud-native resources.
<br />
<br />
If you have any questions or feedback, please join our
<a
class="link"
href="https://join.slack.com/t/k8slens/shared_invite/zt-wcl8jq3k-68R5Wcmk1o95MLBE5igUDQ"
rel="noreferrer"
target="_blank"
>
Lens Community slack channel
</a>
.
</p>
<ul
class="block"
data-testid="welcome-menu-container"
style="width: 320px;"
>
<li
class="flex grid-12"
>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="view_list"
>
view_list
</span>
</i>
<a
class="box col-10"
>
Browse Clusters in Catalog
</a>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="navigate_next"
>
navigate_next
</span>
</i>
</li>
</ul>
</div>
</div>
</div>
</div>
</main>
<div
class="HotbarMenu flex column"
>
<div
class="HotbarItems flex column gaps"
/>
<div
class="HotbarSelector"
>
<i
class="Icon Icon previous material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_left"
>
arrow_left
</span>
</i>
<div
class="HotbarIndex"
>
<div
class="badge Badge small clickable"
id="hotbarIndex"
>
0
</div>
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_right"
>
arrow_right
</span>
</i>
</div>
</div>
<div
class="StatusBar"
>
<div
class="leftSide"
data-testid="status-bar-left"
/>
<div
class="rightSide"
data-testid="status-bar-right"
/>
</div>
</div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
exports[`force user to update when too long since update was downloaded when application is started given checking for updates and it resolves, when update was downloaded when enough time passes to consider that update must be installed renders 1`] = `
<body>
<div>
<div
class="ClusterManager"
>
<div
class="topBar"
>
<div
class="items"
>
<i
class="Icon material interactive focusable"
data-testid="home-button"
tabindex="0"
>
<span
class="icon"
data-icon-name="home"
>
home
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-back"
>
<span
class="icon"
data-icon-name="arrow_back"
>
arrow_back
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-forward"
>
<span
class="icon"
data-icon-name="arrow_forward"
>
arrow_forward
</span>
</i>
<button
class="updateButton"
data-testid="update-button"
data-warning-level="light"
id="update-lens-button"
>
Update
<i
class="Icon icon material focusable"
>
<span
class="icon"
data-icon-name="arrow_drop_down"
>
arrow_drop_down
</span>
</i>
</button>
</div>
<div
class="items"
/>
</div>
<main>
<div
id="lens-views"
/>
<div
class="flex justify-center Welcome align-center"
data-testid="welcome-page"
>
<div
data-testid="welcome-banner-container"
style="width: 320px;"
>
<i
class="Icon logo svg focusable"
>
<span
class="icon"
/>
</i>
<div
class="flex justify-center"
>
<div
data-testid="welcome-text-container"
style="width: 320px;"
>
<h2>
Welcome to OpenLens 5!
</h2>
<p>
To get you started we have auto-detected your clusters in your
kubeconfig file and added them to the catalog, your centralized
view for managing all your cloud-native resources.
<br />
<br />
If you have any questions or feedback, please join our
<a
class="link"
href="https://join.slack.com/t/k8slens/shared_invite/zt-wcl8jq3k-68R5Wcmk1o95MLBE5igUDQ"
rel="noreferrer"
target="_blank"
>
Lens Community slack channel
</a>
.
</p>
<ul
class="block"
data-testid="welcome-menu-container"
style="width: 320px;"
>
<li
class="flex grid-12"
>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="view_list"
>
view_list
</span>
</i>
<a
class="box col-10"
>
Browse Clusters in Catalog
</a>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="navigate_next"
>
navigate_next
</span>
</i>
</li>
</ul>
</div>
</div>
</div>
</div>
</main>
<div
class="HotbarMenu flex column"
>
<div
class="HotbarItems flex column gaps"
/>
<div
class="HotbarSelector"
>
<i
class="Icon Icon previous material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_left"
>
arrow_left
</span>
</i>
<div
class="HotbarIndex"
>
<div
class="badge Badge small clickable"
id="hotbarIndex"
>
0
</div>
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_right"
>
arrow_right
</span>
</i>
</div>
</div>
<div
class="StatusBar"
>
<div
class="leftSide"
data-testid="status-bar-left"
/>
<div
class="rightSide"
data-testid="status-bar-right"
/>
</div>
</div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
<div
class="Animate opacity-scale Dialog flex center modal pinned enter"
style="--enter-duration: 100ms; --leave-duration: 100ms;"
>
<div
class="box"
>
<div
class="ForceUpdateModal"
data-testid="must-update-immediately"
>
<div
class="header"
>
<h2>
Please update
</h2>
</div>
<div
class="content"
>
<p>
An update to Lens Desktop is required to continue using the application.
</p>
</div>
<div
class="footer"
>
<button
class="Button primary"
data-testid="update-now-from-must-update-immediately-modal"
type="button"
>
Update
(
<span
data-testid="countdown-to-automatic-update"
>
5
</span>
)
</button>
</div>
</div>
</div>
</div>
</body>
`;
exports[`force user to update when too long since update was downloaded when application is started given checking for updates and it resolves, when update was downloaded when not enough time passes to consider that update must be installed renders 1`] = `
<body>
<div>
<div
class="ClusterManager"
>
<div
class="topBar"
>
<div
class="items"
>
<i
class="Icon material interactive focusable"
data-testid="home-button"
tabindex="0"
>
<span
class="icon"
data-icon-name="home"
>
home
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-back"
>
<span
class="icon"
data-icon-name="arrow_back"
>
arrow_back
</span>
</i>
<i
class="Icon material interactive disabled focusable"
data-testid="history-forward"
>
<span
class="icon"
data-icon-name="arrow_forward"
>
arrow_forward
</span>
</i>
<button
class="updateButton"
data-testid="update-button"
data-warning-level="light"
id="update-lens-button"
>
Update
<i
class="Icon icon material focusable"
>
<span
class="icon"
data-icon-name="arrow_drop_down"
>
arrow_drop_down
</span>
</i>
</button>
</div>
<div
class="items"
/>
</div>
<main>
<div
id="lens-views"
/>
<div
class="flex justify-center Welcome align-center"
data-testid="welcome-page"
>
<div
data-testid="welcome-banner-container"
style="width: 320px;"
>
<i
class="Icon logo svg focusable"
>
<span
class="icon"
/>
</i>
<div
class="flex justify-center"
>
<div
data-testid="welcome-text-container"
style="width: 320px;"
>
<h2>
Welcome to OpenLens 5!
</h2>
<p>
To get you started we have auto-detected your clusters in your
kubeconfig file and added them to the catalog, your centralized
view for managing all your cloud-native resources.
<br />
<br />
If you have any questions or feedback, please join our
<a
class="link"
href="https://join.slack.com/t/k8slens/shared_invite/zt-wcl8jq3k-68R5Wcmk1o95MLBE5igUDQ"
rel="noreferrer"
target="_blank"
>
Lens Community slack channel
</a>
.
</p>
<ul
class="block"
data-testid="welcome-menu-container"
style="width: 320px;"
>
<li
class="flex grid-12"
>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="view_list"
>
view_list
</span>
</i>
<a
class="box col-10"
>
Browse Clusters in Catalog
</a>
<i
class="Icon box col-1 material focusable"
>
<span
class="icon"
data-icon-name="navigate_next"
>
navigate_next
</span>
</i>
</li>
</ul>
</div>
</div>
</div>
</div>
</main>
<div
class="HotbarMenu flex column"
>
<div
class="HotbarItems flex column gaps"
/>
<div
class="HotbarSelector"
>
<i
class="Icon Icon previous material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_left"
>
arrow_left
</span>
</i>
<div
class="HotbarIndex"
>
<div
class="badge Badge small clickable"
id="hotbarIndex"
>
0
</div>
</div>
<i
class="Icon material interactive focusable"
tabindex="0"
>
<span
class="icon"
data-icon-name="arrow_right"
>
arrow_right
</span>
</i>
</div>
</div>
<div
class="StatusBar"
>
<div
class="leftSide"
data-testid="status-bar-left"
/>
<div
class="rightSide"
data-testid="status-bar-right"
/>
</div>
</div>
<div
class="Notifications flex column align-flex-end"
/>
</div>
</body>
`;
@@ -0,0 +1,148 @@
/**
* 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 type { CheckForPlatformUpdates } from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
import checkForPlatformUpdatesInjectable from "../../main/application-update/check-for-platform-updates/check-for-platform-updates.injectable";
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { DiContainer } from "@ogre-tools/injectable";
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
import type { RenderResult } from "@testing-library/react";
import { fireEvent } from "@testing-library/react";
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
import timeAfterUpdateMustBeInstalledInjectable from "../../renderer/application-update/force-update-modal/time-after-update-must-be-installed.injectable";
import secondsAfterInstallStartsInjectable from "../../renderer/application-update/force-update-modal/seconds-after-install-starts.injectable";
const TIME_AFTER_UPDATE_MUST_BE_INSTALLED = 1000;
const TIME_AFTER_INSTALL_STARTS = 5 * 1000;
describe("force user to update when too long since update was downloaded", () => {
let applicationBuilder: ApplicationBuilder;
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
let mainDi: DiContainer;
let quitAndInstallUpdateMock: jest.Mock;
beforeEach(() => {
useFakeTime("2015-10-21T07:28:00Z");
applicationBuilder = getApplicationBuilder();
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
checkForPlatformUpdatesMock = asyncFn();
mainDi.override(checkForPlatformUpdatesInjectable, () => checkForPlatformUpdatesMock);
downloadPlatformUpdateMock = asyncFn();
mainDi.override(downloadPlatformUpdateInjectable, () => downloadPlatformUpdateMock);
quitAndInstallUpdateMock = jest.fn();
mainDi.override(quitAndInstallUpdateInjectable, () => quitAndInstallUpdateMock);
rendererDi.override(timeAfterUpdateMustBeInstalledInjectable, () => TIME_AFTER_UPDATE_MUST_BE_INSTALLED);
rendererDi.override(secondsAfterInstallStartsInjectable, () => TIME_AFTER_INSTALL_STARTS / 1000);
});
mainDi = applicationBuilder.dis.mainDi;
});
describe("when application is started", () => {
let rendered: RenderResult;
beforeEach(async () => {
rendered = await applicationBuilder.render();
});
describe("given checking for updates and it resolves, when update was downloaded", () => {
beforeEach(async () => {
const processCheckingForUpdates = mainDi.inject(
processCheckingForUpdatesInjectable,
);
processCheckingForUpdates("irrelevant");
await checkForPlatformUpdatesMock.resolve({
updateWasDiscovered: true,
version: "42.0.0",
});
await downloadPlatformUpdateMock.resolve({
downloadWasSuccessful: true,
});
});
it("does not show modal yet", () => {
expect(rendered.queryByTestId("must-update-immediately")).not.toBeInTheDocument();
});
describe("when not enough time passes to consider that update must be installed", () => {
beforeEach(() => {
advanceFakeTime(TIME_AFTER_UPDATE_MUST_BE_INSTALLED - 1);
});
it("does not show modal yet", () => {
expect(rendered.queryByTestId("must-update-immediately")).not.toBeInTheDocument();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
describe("when enough time passes to consider that update must be installed", () => {
beforeEach(() => {
advanceFakeTime(TIME_AFTER_UPDATE_MUST_BE_INSTALLED);
});
it("shows modal to inform about forced update", () => {
expect(rendered.getByTestId("must-update-immediately")).toBeInTheDocument();
});
it("when selected to update now, restarts the application to update", () => {
fireEvent.click(rendered.getByTestId("update-now-from-must-update-immediately-modal"));
expect(quitAndInstallUpdateMock).toHaveBeenCalled();
});
it("shows countdown for automatic update", () => {
expect(rendered.getByTestId("countdown-to-automatic-update")).toHaveTextContent("5");
});
it("when some time passes, updates the countdown for automatic update", () => {
advanceFakeTime(1000);
expect(rendered.getByTestId("countdown-to-automatic-update")).toHaveTextContent("4");
});
it("when not enough time passes for automatic update, does not restart the application yet", () => {
advanceFakeTime(TIME_AFTER_INSTALL_STARTS - 1);
expect(quitAndInstallUpdateMock).not.toHaveBeenCalled();
});
it("when enough time passes for automatically update, restarts the application to update", () => {
advanceFakeTime(TIME_AFTER_INSTALL_STARTS);
expect(quitAndInstallUpdateMock).toHaveBeenCalled();
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
});
});
});
});