mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Rename old directory for behaviours as "features" to better communicate new intent with new directory structure to organize code and tests around features instead of technicalities (#6033)
Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
1 parent
36077a9fea
commit
299922c8a7
107 files changed
No files matched your search
+708
@@ -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!
|
||||
</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!
|
||||
</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!
|
||||
</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>
|
||||
`;
|
||||
+423
@@ -0,0 +1,423 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`encourage user to update when sufficient time passed since update was downloaded when started given the update check when update downloaded given some time passes, when checking for updates again when checking for updates resolves with same version that was previously 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!
|
||||
</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[`encourage user to update when sufficient time passed since update was downloaded when started 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>
|
||||
</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!
|
||||
</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>
|
||||
`;
|
||||
+1249
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+203
@@ -0,0 +1,203 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`periodical checking of updates given updater is enabled and configuration exists, when started 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>
|
||||
</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!
|
||||
</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>
|
||||
`;
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`selection of update stability when started 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>
|
||||
</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!
|
||||
</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,264 @@
|
||||
/**
|
||||
* 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 electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
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 appEventBusInjectable from "../../common/app-event-bus/app-event-bus.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-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 quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
|
||||
describe("analytics for installing update", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let analyticsListenerMock: jest.Mock;
|
||||
let mainDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
analyticsListenerMock = jest.fn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(appVersionInjectable, () => "42.0.0");
|
||||
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
|
||||
mainDi.override(
|
||||
checkForPlatformUpdatesInjectable,
|
||||
() => checkForPlatformUpdatesMock,
|
||||
);
|
||||
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
|
||||
mainDi.override(downloadPlatformUpdateInjectable, () => downloadPlatformUpdateMock);
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
|
||||
const eventBus = mainDi.inject(appEventBusInjectable);
|
||||
|
||||
eventBus.addListener(analyticsListenerMock);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
});
|
||||
|
||||
describe("given application is started and checking updates periodically", () => {
|
||||
beforeEach(async () => {
|
||||
mainDi.unoverride(periodicalCheckForUpdatesInjectable);
|
||||
mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable);
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
});
|
||||
|
||||
it("sends event to analytics for being checked periodically", () => {
|
||||
expect(analyticsListenerMock).toHaveBeenCalledWith({
|
||||
name: "app",
|
||||
action: "checking-for-updates",
|
||||
|
||||
params: {
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
source: "periodic",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("when enough time passes to check for updates again, sends event to analytics for being checked periodically", () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
advanceFakeTime(1000 * 60 * 60 * 2);
|
||||
|
||||
expect(analyticsListenerMock).toHaveBeenCalledWith({
|
||||
name: "app",
|
||||
action: "checking-for-updates",
|
||||
|
||||
params: {
|
||||
currentDateTime: "2015-10-21T09:28:00Z",
|
||||
source: "periodic",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when application is started", () => {
|
||||
beforeEach(async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("sends event to analytics about the current version", () => {
|
||||
expect(analyticsListenerMock).toHaveBeenCalledWith({
|
||||
name: "app",
|
||||
action: "current-version",
|
||||
|
||||
params: {
|
||||
version: "42.0.0",
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("when checking for updates using tray, sends event to analytics for being checked from tray", async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
name: "app",
|
||||
action: "checking-for-updates",
|
||||
|
||||
params: {
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
source: "tray",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
});
|
||||
|
||||
it("when checking for updates using application menu, sends event to analytics for being checked from application menu", async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
applicationBuilder.applicationMenu.click("root.check-for-updates");
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
name: "app",
|
||||
action: "checking-for-updates",
|
||||
|
||||
params: {
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
source: "application-menu",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
describe("given checking for updates, when check for updates resolves with new update being available", () => {
|
||||
beforeEach(async () => {
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "43.0.0",
|
||||
});
|
||||
});
|
||||
|
||||
it("sends event to analytics about new update being available", () => {
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
name: "app",
|
||||
action: "update-was-discovered",
|
||||
|
||||
params: {
|
||||
version: "43.0.0",
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
describe("given update is downloaded", () => {
|
||||
beforeEach(async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
|
||||
});
|
||||
|
||||
describe("given checking for updates again", () => {
|
||||
beforeEach(() => {
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
analyticsListenerMock.mockClear();
|
||||
});
|
||||
|
||||
it("when check resolves with same version that was previously downloaded, does not send event to analytics about update discovered", async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "43.0.0",
|
||||
});
|
||||
|
||||
expect(analyticsListenerMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when check resolves with different version that was previously downloaded, sends event to analytics about update discovered", async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "44.0.0",
|
||||
});
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
name: "app",
|
||||
action: "update-was-discovered",
|
||||
|
||||
params: {
|
||||
version: "44.0.0",
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it("does not send event to analytics about update downloaded being successful", () => {
|
||||
expect(analyticsListenerMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when installing the update, sends event to analytics about installing the update", () => {
|
||||
const quitAndInstallUpdate = mainDi.inject(quitAndInstallUpdateInjectable);
|
||||
|
||||
quitAndInstallUpdate();
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
name: "app",
|
||||
action: "start-installing-update",
|
||||
|
||||
params: {
|
||||
version: "43.0.0",
|
||||
currentDateTime: "2015-10-21T07:28:00Z",
|
||||
updateChannel: "latest",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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 electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
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 processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../common/application-update/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
||||
import { updateChannels } from "../../common/application-update/update-channels";
|
||||
|
||||
describe("downgrading version update", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let mainDi: DiContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
|
||||
mainDi.override(
|
||||
checkForPlatformUpdatesInjectable,
|
||||
() => checkForPlatformUpdatesMock,
|
||||
);
|
||||
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
});
|
||||
|
||||
[
|
||||
{
|
||||
updateChannel: updateChannels.latest,
|
||||
appVersion: "4.0.0-beta",
|
||||
downgradeIsAllowed: true,
|
||||
},
|
||||
{
|
||||
updateChannel: updateChannels.beta,
|
||||
appVersion: "4.0.0-beta",
|
||||
downgradeIsAllowed: false,
|
||||
},
|
||||
{
|
||||
updateChannel: updateChannels.beta,
|
||||
appVersion: "4.0.0-beta.1",
|
||||
downgradeIsAllowed: false,
|
||||
},
|
||||
{
|
||||
updateChannel: updateChannels.alpha,
|
||||
appVersion: "4.0.0-beta",
|
||||
downgradeIsAllowed: true,
|
||||
},
|
||||
{
|
||||
updateChannel: updateChannels.alpha,
|
||||
appVersion: "4.0.0-alpha",
|
||||
downgradeIsAllowed: false,
|
||||
},
|
||||
].forEach(({ appVersion, updateChannel, downgradeIsAllowed }) => {
|
||||
it(`given application version "${appVersion}" and update channel "${updateChannel.id}", when checking for updates, can${downgradeIsAllowed ? "": "not"} downgrade`, async () => {
|
||||
mainDi.override(appVersionInjectable, () => appVersion);
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable);
|
||||
|
||||
selectedUpdateChannel.setValue(updateChannel.id);
|
||||
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(expect.any(Object), { allowDowngrade: downgradeIsAllowed });
|
||||
});
|
||||
});
|
||||
});
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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";
|
||||
import forceUpdateModalRootFrameComponentInjectable from "../../renderer/application-update/force-update-modal/force-update-modal-root-frame-component.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 }) => {
|
||||
rendererDi.unoverride(forceUpdateModalRootFrameComponentInjectable);
|
||||
rendererDi.permitSideEffects(forceUpdateModalRootFrameComponentInjectable);
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { act } from "@testing-library/react";
|
||||
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 publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
|
||||
function daysToMilliseconds(days: number) {
|
||||
return Math.round(days * 24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
describe("encourage user to update when sufficient time passed since update was downloaded", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let quitAndInstallUpdateMock: jest.MockedFunction<() => void>;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
|
||||
mainDi.override(
|
||||
checkForPlatformUpdatesInjectable,
|
||||
() => checkForPlatformUpdatesMock,
|
||||
);
|
||||
|
||||
mainDi.override(
|
||||
downloadPlatformUpdateInjectable,
|
||||
() => downloadPlatformUpdateMock,
|
||||
);
|
||||
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
mainDi.override(quitAndInstallUpdateInjectable, () => quitAndInstallUpdateMock);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when started", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not show update button yet", () => {
|
||||
const button = rendered.queryByTestId("update-button");
|
||||
|
||||
expect(button).toBeNull();
|
||||
});
|
||||
|
||||
describe("given the update check", () => {
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(
|
||||
processCheckingForUpdatesInjectable,
|
||||
);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
describe("when update downloaded", () => {
|
||||
let button: HTMLElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
|
||||
|
||||
button = rendered.getByTestId("update-button");
|
||||
});
|
||||
|
||||
it("shows update button to help user to update", () => {
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("has soft emotional indication in the button", () => {
|
||||
expect(button).toHaveAttribute("data-warning-level", "light");
|
||||
});
|
||||
|
||||
// TODO: Implement after starting main and renderer is separated in ApplicationBuilder
|
||||
xit("given closing the application window, when starting the application window again, still shows the button", () => {
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("given some time passes, when checking for updates again", () => {
|
||||
beforeEach(() => {
|
||||
advanceFakeTime(daysToMilliseconds(2));
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
describe("when checking for updates resolves with same version that was previously downloaded", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
});
|
||||
|
||||
it("when enough time from download passes for medium update encouragement, has medium emotional indication in the button", () => {
|
||||
advanceFakeTime(daysToMilliseconds(20));
|
||||
|
||||
expect(button).toHaveAttribute("data-warning-level", "medium");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when button is clicked", () => {
|
||||
beforeEach(() => {
|
||||
act(() => button.click());
|
||||
});
|
||||
|
||||
it("shows dropdown with update item", () => {
|
||||
expect(rendered.getByTestId("update-lens-menu-item")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("when selected update now, restarts the application to update", () => {
|
||||
const updateMenuItem = rendered.getByTestId("update-lens-menu-item");
|
||||
|
||||
act(() => updateMenuItem.click());
|
||||
|
||||
expect(quitAndInstallUpdateMock).toBeCalled();
|
||||
});
|
||||
|
||||
it("when dropdown closed without clicking update item, does not restart the application to update", () => {
|
||||
act(() => button.click());
|
||||
|
||||
expect(quitAndInstallUpdateMock).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("given just enough time passes for medium update encouragement, has medium emotional indication in the button", () => {
|
||||
advanceFakeTime(daysToMilliseconds(22));
|
||||
|
||||
expect(button).toHaveAttribute("data-warning-level", "medium");
|
||||
});
|
||||
|
||||
it("given just enough time passes for severe update encouragement, has severe emotional indication in the button", () => {
|
||||
advanceFakeTime(daysToMilliseconds(26));
|
||||
|
||||
expect(button).toHaveAttribute("data-warning-level", "high");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* 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 { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
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 { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
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 closeAllWindowsInjectable from "../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
|
||||
describe("installing update using tray", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
|
||||
mainDi.override(
|
||||
checkForPlatformUpdatesInjectable,
|
||||
() => checkForPlatformUpdatesMock,
|
||||
);
|
||||
|
||||
mainDi.override(
|
||||
downloadPlatformUpdateInjectable,
|
||||
() => downloadPlatformUpdateMock,
|
||||
);
|
||||
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when started", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("user cannot install update yet", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
describe("given all application windows are closed, when checking for updates", () => {
|
||||
let applicationWindow: LensWindow;
|
||||
let closeAllWindows: () => void;
|
||||
|
||||
beforeEach(() => {
|
||||
const mainDi = applicationBuilder.dis.mainDi;
|
||||
|
||||
closeAllWindows = mainDi.inject(closeAllWindowsInjectable);
|
||||
|
||||
applicationWindow = mainDi.inject(applicationWindowInjectable);
|
||||
|
||||
closeAllWindows();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
});
|
||||
|
||||
describe("when check for update resolves with new update", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not show application window yet", () => {
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
});
|
||||
|
||||
describe("when download of update resolves with success", () => {
|
||||
beforeEach(async () => {
|
||||
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
|
||||
});
|
||||
|
||||
it("shows the application window", () => {
|
||||
expect(applicationWindow.isVisible).toBe(true);
|
||||
});
|
||||
|
||||
it("given closing application window again and checking for updates again using tray, when check resolves with same version that was earlier downloaded, shows the application window", async () => {
|
||||
closeAllWindows();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("when download of update resolves with failure, does not show the application window", async () => {
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false });
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it("when process resolves without new update, does not show the application window", async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: false,
|
||||
});
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when user checks for updates using tray", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
});
|
||||
|
||||
it("user cannot check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Checking for updates...");
|
||||
});
|
||||
|
||||
it("user cannot install update yet", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when no new update is discovered", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("user cannot install update", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when new update is discovered", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
});
|
||||
|
||||
it("user cannot check for updates again yet", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Downloading update some-version (0%)...");
|
||||
});
|
||||
|
||||
it("when download progresses with decimals, percentage increases as integers", () => {
|
||||
downloadPlatformUpdateMock.mock.calls[0][0]({ percentage: 42.424242 });
|
||||
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Downloading update some-version (42%)...");
|
||||
});
|
||||
|
||||
it("user still cannot install update", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when download fails", () => {
|
||||
beforeEach(async () => {
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false });
|
||||
});
|
||||
|
||||
it("user cannot install update", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("install-update"),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when download succeeds", () => {
|
||||
beforeEach(async () => {
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
|
||||
});
|
||||
|
||||
it("user can install update", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("install-update")?.label,
|
||||
).toBe("Install update some-version");
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,246 @@
|
||||
/**
|
||||
* 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/application-update/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/application-update/publish-is-configured.injectable";
|
||||
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 { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
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 setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import { useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
||||
|
||||
describe("installing update", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let quitAndInstallUpdateMock: jest.Mock;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let setUpdateOnQuitMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
setUpdateOnQuitMock = jest.fn();
|
||||
|
||||
mainDi.override(staticFilesDirectoryInjectable, () => "/some-static-files-directory");
|
||||
|
||||
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("when started", () => {
|
||||
let rendered: RenderResult;
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(
|
||||
processCheckingForUpdatesInjectable,
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when user checks for updates", () => {
|
||||
beforeEach(() => {
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
it("checks for updates", () => {
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||
expect.any(Object),
|
||||
{ allowDowngrade: true },
|
||||
);
|
||||
});
|
||||
|
||||
it("shows tray icon for checking for updates", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when no new update is discovered", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("shows tray icon for normal", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
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",
|
||||
});
|
||||
});
|
||||
|
||||
it("starts downloading the update", () => {
|
||||
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("still shows tray icon for downloading", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
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("still shows normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
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("shows tray icon for update being available", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("given checking for updates again", () => {
|
||||
beforeEach(() => {
|
||||
downloadPlatformUpdateMock.mockClear();
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
it("shows tray icon for checking for updates", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
describe("when check resolves with same update that is already downloaded", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not re-download the update", () => {
|
||||
expect(downloadPlatformUpdateMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows tray icon for update being available", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when check resolves with different update that was previously downloaded", () => {
|
||||
beforeEach(async () => {
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-other-version",
|
||||
});
|
||||
});
|
||||
|
||||
it("downloads the update", () => {
|
||||
expect(downloadPlatformUpdateMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows tray icon for downloading update", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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 { RenderResult } from "@testing-library/react";
|
||||
import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable";
|
||||
import publishIsConfiguredInjectable from "../../main/application-update/publish-is-configured.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
|
||||
const ENOUGH_TIME = 1000 * 60 * 60 * 2;
|
||||
|
||||
describe("periodical checking of updates", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let processCheckingForUpdatesMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.unoverride(periodicalCheckForUpdatesInjectable);
|
||||
mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdatesMock = jest.fn();
|
||||
|
||||
mainDi.override(
|
||||
processCheckingForUpdatesInjectable,
|
||||
() => processCheckingForUpdatesMock,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given updater is enabled and configuration exists, when started", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("checks for updates", () => {
|
||||
expect(processCheckingForUpdatesMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when just not enough time passes, does not check for updates again automatically yet", () => {
|
||||
processCheckingForUpdatesMock.mockClear();
|
||||
|
||||
advanceFakeTime(ENOUGH_TIME - 1);
|
||||
|
||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when just enough time passes, checks for updates again automatically", () => {
|
||||
processCheckingForUpdatesMock.mockClear();
|
||||
|
||||
advanceFakeTime(ENOUGH_TIME);
|
||||
|
||||
expect(processCheckingForUpdatesMock).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("given updater is enabled but no configuration exist, when started", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => false);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("does not check for updates", () => {
|
||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when time passes, never checks for updates", () => {
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("given updater is not enabled but and configuration exist, when started", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => false);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("does not check for updates", () => {
|
||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when time passes, never checks for updates", () => {
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,326 @@
|
||||
/**
|
||||
* 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/application-update/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/application-update/publish-is-configured.injectable";
|
||||
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 { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { UpdateChannel, UpdateChannelId } from "../../common/application-update/update-channels";
|
||||
import { updateChannels } from "../../common/application-update/update-channels";
|
||||
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 selectedUpdateChannelInjectable from "../../common/application-update/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
||||
import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
||||
|
||||
describe("selection of update stability", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let quitAndInstallUpdateMock: jest.Mock;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let setUpdateOnQuitMock: jest.Mock;
|
||||
let showInfoNotificationMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
setUpdateOnQuitMock = jest.fn();
|
||||
showInfoNotificationMock = jest.fn(() => () => {});
|
||||
|
||||
rendererDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock);
|
||||
|
||||
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("when started", () => {
|
||||
let rendered: RenderResult;
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
it('checks updates from update channel "alpha"', () => {
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||
updateChannels.alpha,
|
||||
{ allowDowngrade: true },
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
{ allowDowngrade: true },
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
{ allowDowngrade: true },
|
||||
);
|
||||
});
|
||||
|
||||
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(() => {
|
||||
processCheckingForUpdates("irrelevant");
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
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 processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.latest, expect.any(Object));
|
||||
});
|
||||
|
||||
it('given no update channel selection is stored and currently using stable release, when user checks for updates, checks for updates from "latest" update channel by default', async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(appVersionInjectable, () => "1.0.0");
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(
|
||||
updateChannels.latest,
|
||||
{ allowDowngrade: true },
|
||||
);
|
||||
});
|
||||
|
||||
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 processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
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 processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
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 processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
expect(checkForPlatformUpdatesMock).toHaveBeenCalledWith(updateChannels.beta, expect.any(Object));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user