Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CP-1742] fixes after QA #1089

Merged
merged 5 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[CP-1742] silent check for update works fine after cabel unplug
  • Loading branch information
wojcik92michal committed Jan 17, 2023
commit 38be7e173ed0aa7f9bcf37942cc60b213e722c44
3 changes: 3 additions & 0 deletions packages/app/src/__deprecated__/renderer/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ export const { select } = store
export type RootState = RematchRootState<typeof models>
export type Store = typeof store
export type Dispatch = RematchDispatch<RootModel>
export type RejectableThunk = {
abort: () => void
}

// TODO replace `TmpDispatch` with legit `Dispatch`
// AUTO DISABLED - fix me if you like :)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
UpdateError,
} from "App/update/constants"
import { OsRelease, ProcessedRelease } from "App/update/dto"
import { RejectableThunk } from "App/__deprecated__/renderer/store"

export interface HarmonyOverviewProps {
readonly lowestSupportedOsVersion: string | undefined
Expand All @@ -36,7 +37,7 @@ export interface HarmonyOverviewProps {
readonly checkForUpdate: (
deviceType: DeviceType,
mode: CheckForUpdateMode
) => void
) => RejectableThunk
readonly setCheckForUpdateState: (state: State) => void
readonly downloadUpdates: (releases: OsRelease[]) => void
readonly clearUpdateState: () => void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
import { State } from "App/core/constants"
import { DeviceType } from "App/device/constants"
import { Feature, flags } from "App/feature-flags"
import { CheckForUpdateLocalState } from "App/overview/components/overview-screens/constants/overview.enum"
import { HarmonyOverviewProps } from "App/overview/components/overview-screens/harmony-overview/harmony-overview.component.interface"
import OverviewContent from "App/overview/components/overview-screens/harmony-overview/overview-content.component"
import { CheckForUpdateLocalState } from "App/overview/components/overview-screens/overview.enum"
import { useUpdateFlowState } from "App/overview/components/overview-screens/helpers/use-update-flow-state.hook"
import { UpdateOsFlow } from "App/overview/components/update-os-flow"
import UpdatingForceModalFlow from "App/overview/components/updating-force-modal-flow/updating-force-modal-flow.component"
import { UpdatingForceModalFlowState } from "App/overview/components/updating-force-modal-flow/updating-force-modal-flow.enum"
import isVersionGreaterOrEqual from "App/overview/helpers/is-version-greater-or-equal"
import {
CheckForUpdateMode,
SilentCheckForUpdateState,
} from "App/update/constants"
import { CheckForUpdateMode } from "App/update/constants"
import { OsRelease } from "App/update/dto"
import { HelpActions } from "App/__deprecated__/common/enums/help-actions.enum"
import logger from "App/__deprecated__/main/utils/logger"
Expand Down Expand Up @@ -51,8 +49,12 @@ export const HarmonyOverview: FunctionComponent<HarmonyOverviewProps> = ({
setCheckForUpdateState,
}) => {
const [osVersionSupported, setOsVersionSupported] = useState(true)
const [checkForUpdateLocalState, setCheckForUpdateLocalState] =
useState<CheckForUpdateLocalState>()
const { checkForUpdateLocalState } = useUpdateFlowState({
checkingForUpdateState,
silentCheckForUpdateState,
checkForUpdate: () =>
checkForUpdate(DeviceType.MuditaHarmony, CheckForUpdateMode.SilentCheck),
})

useEffect(() => {
try {
Expand All @@ -64,48 +66,11 @@ export const HarmonyOverview: FunctionComponent<HarmonyOverviewProps> = ({
}
}, [osVersion, lowestSupportedOsVersion])

useEffect(() => {
if (silentCheckForUpdateState === SilentCheckForUpdateState.Initial) {
harmonySilentCheckForUpdate()
}
// AUTO DISABLED - fix me if you like :)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [silentCheckForUpdateState])

useEffect(() => {
if (
silentCheckForUpdateState === SilentCheckForUpdateState.Failed ||
checkingForUpdateState === State.Failed
) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Failed)
}

if (silentCheckForUpdateState === SilentCheckForUpdateState.Loading) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.SilentCheckLoading)
}

if (checkingForUpdateState === State.Loading) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Loading)
}

if (
silentCheckForUpdateState === SilentCheckForUpdateState.Loaded ||
checkingForUpdateState === State.Loaded
) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Loaded)
}
}, [silentCheckForUpdateState, checkingForUpdateState])

const goToHelp = (): void => {
void ipcRenderer.callMain(HelpActions.OpenWindow)
}

const harmonySilentCheckForUpdate = () =>
checkForUpdate(DeviceType.MuditaHarmony, CheckForUpdateMode.SilentCheck)

// AUTO DISABLED - fix me if you like :)
// eslint-disable-next-line @typescript-eslint/require-await
const closeUpdatingForceModalFlow = async () => {
const closeUpdatingForceModalFlow = () => {
setUpdateState(State.Initial)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import { State } from "App/core/constants"
import { CheckForUpdateLocalState } from "App/overview/components/overview-screens/constants/overview.enum"
import { SilentCheckForUpdateState } from "App/update/constants"
import { RejectableThunk } from "App/__deprecated__/renderer/store"
import { useEffect, useState } from "react"

interface Params {
silentCheckForUpdateState: SilentCheckForUpdateState
checkingForUpdateState: State
checkForUpdate: () => RejectableThunk
}

interface Result {
checkForUpdateLocalState: CheckForUpdateLocalState | undefined
}

export const useUpdateFlowState = ({
checkingForUpdateState,
silentCheckForUpdateState,
checkForUpdate,
}: Params): Result => {
const [checkForUpdateLocalState, setCheckForUpdateLocalState] =
useState<CheckForUpdateLocalState>()
const [silentCheckForUpdatePromise, setSilentCheckForUpdatePromise] =
useState<RejectableThunk>()

useEffect(() => {
if (silentCheckForUpdateState === SilentCheckForUpdateState.Initial) {
const actionResult = checkForUpdate()
setSilentCheckForUpdatePromise(actionResult)
}

return () => {
if (
silentCheckForUpdatePromise &&
silentCheckForUpdateState === SilentCheckForUpdateState.Loading
) {
silentCheckForUpdatePromise.abort()
setSilentCheckForUpdatePromise(undefined)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [silentCheckForUpdateState])

useEffect(() => {
if (
silentCheckForUpdateState === SilentCheckForUpdateState.Failed ||
checkingForUpdateState === State.Failed
) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Failed)
}

if (silentCheckForUpdateState === SilentCheckForUpdateState.Loading) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.SilentCheckLoading)
}

if (checkingForUpdateState === State.Loading) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Loading)
}

if (
silentCheckForUpdateState === SilentCheckForUpdateState.Loaded ||
checkingForUpdateState === State.Loaded
) {
setCheckForUpdateLocalState(CheckForUpdateLocalState.Loaded)
}
}, [silentCheckForUpdateState, checkingForUpdateState])
return {
checkForUpdateLocalState,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* Copyright (c) Mudita sp. z o.o. All rights reserved.
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import { renderHook } from "@testing-library/react-hooks"
import { State } from "App/core/constants"
import { CheckForUpdateLocalState } from "App/overview/components/overview-screens/constants/overview.enum"
import { useUpdateFlowState } from "App/overview/components/overview-screens/helpers/use-update-flow-state.hook"
import { SilentCheckForUpdateState } from "App/update/constants"

type TestCase = [
testedState: SilentCheckForUpdateState | State,
expectedState: CheckForUpdateLocalState
]

const defaultParams = {
checkForUpdate: jest.fn(),
checkingForUpdateState: State.Initial,
silentCheckForUpdateState: SilentCheckForUpdateState.Initial,
}

const silentCheckTestCases: TestCase[] = [
[SilentCheckForUpdateState.Failed, CheckForUpdateLocalState.Failed],
[
SilentCheckForUpdateState.Loading,
CheckForUpdateLocalState.SilentCheckLoading,
],
[SilentCheckForUpdateState.Loaded, CheckForUpdateLocalState.Loaded],
]

const checkForUpdateTestCases: TestCase[] = [
[State.Failed, CheckForUpdateLocalState.Failed],
[State.Loading, CheckForUpdateLocalState.Loading],
[State.Loaded, CheckForUpdateLocalState.Loaded],
]

describe.each(silentCheckTestCases)(
"when value for silentCheckForUpdateState equals to %p",
(param, expectedResult) => {
test(`checkForUpdateLocalState should equal to ${expectedResult}`, () => {
const { result } = renderHook(() =>
useUpdateFlowState({
...defaultParams,
silentCheckForUpdateState: param as SilentCheckForUpdateState,
})
)

expect(result.current.checkForUpdateLocalState).toEqual(expectedResult)
})
}
)

describe.each(checkForUpdateTestCases)(
"when value for checkingForUpdateState equals to %p",
(b, c) => {
test(`checkForUpdateLocalState should equal to ${c}`, () => {
const { result } = renderHook(() =>
useUpdateFlowState({
...defaultParams,
checkingForUpdateState: b as State,
})
)

expect(result.current.checkForUpdateLocalState).toEqual(c)
})
}
)

describe("when silentCheckForUpdateState is set as initial", () => {
test("check for update should be called", () => {
const spy = jest.fn()
renderHook(() =>
useUpdateFlowState({
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Initial,
checkForUpdate: spy,
})
)
expect(spy).toHaveBeenCalledTimes(1)
})
})

describe("when silentCheckForUpdateState is not set as initial", () => {
test("check for update should not be called", () => {
const spy = jest.fn()
renderHook(() =>
useUpdateFlowState({
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Loaded,
checkForUpdate: spy,
})
)
expect(spy).toHaveBeenCalledTimes(0)
})
})

describe("when hook is going to be destroyed", () => {
test("should abort pending check for update action", () => {
const abortSpy = jest.fn()
const mockedCheckForUpdate = jest.fn().mockReturnValue({
abort: abortSpy,
})
let params = {
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Initial,
checkForUpdate: mockedCheckForUpdate,
}

const { rerender, unmount } = renderHook(() => useUpdateFlowState(params))

params = {
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Loading,
checkForUpdate: mockedCheckForUpdate,
}

rerender()
unmount()

expect(abortSpy).toHaveBeenCalledTimes(1)
})
test("should not abort check for update action that is not pending", () => {
const abortSpy = jest.fn()
const mockedCheckForUpdate = jest.fn().mockReturnValue({
abort: abortSpy,
})
let params = {
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Initial,
checkForUpdate: mockedCheckForUpdate,
}

const { rerender, unmount } = renderHook(() => useUpdateFlowState(params))

params = {
...defaultParams,
silentCheckForUpdateState: SilentCheckForUpdateState.Loaded,
checkForUpdate: mockedCheckForUpdate,
}

rerender()
unmount()

expect(abortSpy).toHaveBeenCalledTimes(0)
})
})
Loading