Skip to content

Commit

Permalink
Merge pull request #349 from mudita/CP-469
Browse files Browse the repository at this point in the history
[CP-469] Password shows up in MC before Pure boots up and it is failing
  • Loading branch information
dkarski committed Aug 20, 2021
2 parents 93bc50b + d7aaa19 commit ce2e9b3
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 44 deletions.
2 changes: 1 addition & 1 deletion packages/app/jest.coverage.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
"branches": 63.61
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type ResponseError = PureDeviceUpdateError | DeviceUpdateError
export enum DeviceResponseStatus {
Ok = "ok",
PhoneLocked = "phone-locked",
InternalServerError = "internal-server-error",
Error = "error",
}

Expand Down
5 changes: 5 additions & 0 deletions packages/app/src/backend/device-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ class DeviceService {
error,
status: DeviceResponseStatus.PhoneLocked,
}
} else if (status === ResponseStatus.InternalServerError) {
return {
error,
status: DeviceResponseStatus.InternalServerError,
}
} else {
return {
error,
Expand Down
98 changes: 61 additions & 37 deletions packages/app/src/passcod-modal/passcode-modal.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,74 +16,98 @@ export interface PasscodeModalProps {
openModal: boolean
close: () => void
}

enum ErrorState {
NoError,
TypingError,
BadPasscode,
InternalServerError,
}

const ErrorMessageMap: Record<ErrorState, string> = {
[ErrorState.NoError]: "",
[ErrorState.TypingError]: "component.passcodeModalErrorTyping",
[ErrorState.BadPasscode]: "component.passcodeModalError",
[ErrorState.InternalServerError]: "component.passcodeModalTryAgain",
}

let timeoutId3: NodeJS.Timeout

const PasscodeModal: FunctionComponent<PasscodeModalProps> = ({
openModal,
close,
}) => {
const initValue = ["", "", "", ""]
const [error, setError] = useState<boolean>(false)
const [typingError, setTypingError] = useState<boolean>(false)
const [errorState, setErrorState] = useState<ErrorState>(ErrorState.NoError)
const [values, setValues] = useState<string[]>(initValue)

const openHelpWindow = () => ipcRenderer.callMain(HelpActions.OpenWindow)

const updateValues = (values: string[]) => {
const updateValues = (values: string[]): void => {
setValues(values)
}

const onNotAllowedKeyDown = () => {
const onNotAllowedKeyDown = (): void => {
clearTimeout(timeoutId3)
setTypingError(true)
setErrorState(ErrorState.TypingError)
timeoutId3 = setTimeout(() => {
setTypingError(false)
setErrorState(ErrorState.NoError)
}, 1500)
}

const getErrorMessage = () => {
if (error) {
return "component.passcodeModalError"
} else if (typingError) {
return "component.passcodeModalErrorTyping"
} else {
return ""
}
const getErrorMessage = (): string => {
return ErrorMessageMap[errorState]
}

useEffect(() => {
let timeoutId1: NodeJS.Timeout
let timeoutId2: NodeJS.Timeout

const unlockDeviceRequest = async (code: number[]) => {
await unlockDevice(code)
timeoutId1 = setTimeout(async () => {
const { status } = await getUnlockDeviceStatus()

if (status !== DeviceResponseStatus.Ok) {
setError(true)
timeoutId2 = setTimeout(() => {
setError(false)
setValues(initValue)
}, 1500)
}
}, 1000)

return () => {
clearTimeout(timeoutId1)
clearTimeout(timeoutId2)
let timeoutId: NodeJS.Timeout

const unlockDeviceRequest = async (code: number[]): Promise<void> => {
const response = await unlockDevice(code)

if (response.status === DeviceResponseStatus.InternalServerError) {
setErrorState(ErrorState.InternalServerError)
} else {
timeoutId = setTimeout(async () => {
const { status } = await getUnlockDeviceStatus()

if (status !== DeviceResponseStatus.Ok) {
setErrorState(ErrorState.BadPasscode)
}
}, 1000)
}
}

setTypingError(false)

if (values[values.length - 1] !== "") {
const code = values.map((value) => parseInt(value))
void unlockDeviceRequest(code)
} else {
setError(false)
setErrorState(ErrorState.NoError)
}

return () => {
clearTimeout(timeoutId)
}
}, [values])

useEffect(() => {
let timeoutId: NodeJS.Timeout

if (
errorState === ErrorState.BadPasscode ||
errorState === ErrorState.InternalServerError
) {
timeoutId = setTimeout(() => {
setErrorState(ErrorState.NoError)
setValues(initValue)
}, 1500)
}

return () => {
clearTimeout(timeoutId)
}
}, [errorState])

return (
<PasscodeModalUI
openModal={openModal}
Expand Down
56 changes: 52 additions & 4 deletions packages/app/src/passcod-modal/passcode-modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@

import { renderWithThemeAndIntl } from "Renderer/utils/render-with-theme-and-intl"
import PasscodeModal from "./passcode-modal.component"
import React from "react"
import React, { ComponentProps } from "react"
import { PasscodeModalTestIds } from "./passcode-modal-test-ids.enum"
import { fireEvent, waitFor } from "@testing-library/dom"
import { InputTextTestIds } from "App/renderer/components/core/input-text/input-text-test-ids.enum"
import { ipcRenderer } from "electron-better-ipc"
import { IpcRequest } from "Common/requests/ipc-request.enum"
import { DeviceResponseStatus } from "Backend/adapters/device-response.interface"
import { noop } from "Renderer/utils/noop"

const defaultProps = {
type Props = ComponentProps<typeof PasscodeModal>

const defaultProps: Props = {
openModal: true,
close: jest.fn(),
}
const renderer = () => {
const props = {

const renderer = (extraProps?: Partial<Props>) => {
const props: Props = {
...defaultProps,
...extraProps,
}
const modal = renderWithThemeAndIntl(<PasscodeModal {...props} />)
return {
Expand Down Expand Up @@ -54,3 +62,43 @@ test("Show typing error message", async () => {
)
)
})

test("message is displayed properly when request about phone lock return internal server error", async () => {
;(ipcRenderer as any).__rendererCalls = {
[IpcRequest.UnlockDevice]: Promise.resolve({
status: DeviceResponseStatus.InternalServerError,
}),
}
const { inputsList, errorMessage } = renderer()
fireEvent.change(inputsList()[0] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[1] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[2] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[3] as Element, { target: { value: "2" } })
await waitFor(() =>
expect(errorMessage()).toHaveTextContent(
"[value] component.passcodeModalTryAgain"
)
)
})

test("message is displayed properly when request about phone lock status return phone locked", async () => {
;(ipcRenderer as any).__rendererCalls = {
[IpcRequest.UnlockDevice]: Promise.resolve({
status: DeviceResponseStatus.Ok,
}),
[IpcRequest.GetUnlockDeviceStatus]: Promise.resolve({
status: DeviceResponseStatus.PhoneLocked,
}),
}
const { inputsList, errorMessage } = renderer()
fireEvent.change(inputsList()[0] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[1] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[2] as Element, { target: { value: "2" } })
fireEvent.change(inputsList()[3] as Element, { target: { value: "2" } })
await waitFor(noop)
await waitFor(() =>
expect(errorMessage()).toHaveTextContent(
"[value] component.passcodeModalError"
)
)
})
3 changes: 1 addition & 2 deletions packages/app/src/renderer/locales/default/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,5 @@
"module.tools.notesSelectionsNumber": "{num, plural, =-1 {All Notes} one {# Note} other {# Notes}} selected",
"module.tools.notesTemporaryText": "New Note",
"module.tools.notesUnsavedNote": "unsaved",
"module.tools.voiceRecorder": "Voice Recorder",
"test": "test"
"module.tools.voiceRecorder": "Voice Recorder"
}

0 comments on commit ce2e9b3

Please sign in to comment.