0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

refactor(ui): refactor confirmModalPromisify (#1993)

refactor confirmModalPromisify
This commit is contained in:
simeng-li 2022-09-26 11:27:25 +08:00 committed by GitHub
parent d66122f935
commit 649958023d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 56 additions and 37 deletions

View file

@ -1,3 +1,4 @@
export { default as WebModal } from './AcModal';
export { default as MobileModal } from './MobileModal';
export { default as IframeModal } from './IframeConfirmModal';
export { modalPromisify } from './modalPromisify';

View file

@ -1,15 +1,15 @@
import { fireEvent } from '@testing-library/react';
import renderWithPageContext from '@/__mocks__/RenderWithPageContext';
import TermsOfUseConfirmModal from '@/containers/TermsOfUse/TermsOfUseConfirmModal';
import { modalPromisify } from '.';
import TermsOfUseConfirmModal from '../TermsOfUseConfirmModal';
describe('modalPromisify', () => {
const onResolve = jest.fn();
const onReject = jest.fn();
it('render properly', () => {
it('resolve properly', () => {
const PromisifyModal = modalPromisify(TermsOfUseConfirmModal);
const { getByText } = renderWithPageContext(
@ -22,7 +22,7 @@ describe('modalPromisify', () => {
expect(onResolve).toBeCalled();
});
it('reject with message', () => {
it('reject', () => {
const PromisifyModal = modalPromisify(TermsOfUseConfirmModal);
const { getByText } = renderWithPageContext(

View file

@ -1,11 +1,11 @@
import { InstanceProps } from 'react-modal-promise';
import { TermsOfUseModalMessage } from '@/types';
import { ConfirmModalMessage } from '@/types';
type Props = {
isOpen?: boolean;
onConfirm: () => void;
onClose: (message?: TermsOfUseModalMessage) => void;
onClose: (message?: ConfirmModalMessage) => void;
};
export const modalPromisify =
@ -14,14 +14,14 @@ export const modalPromisify =
isOpen,
onResolve,
onReject,
}: Omit<InstanceProps<boolean | TermsOfUseModalMessage>, 'open' | 'close'>) => {
}: Omit<InstanceProps<boolean | ConfirmModalMessage>, 'open' | 'close'>) => {
return (
<ConfirmModal
isOpen={isOpen}
onConfirm={() => {
onResolve(true);
}}
onClose={(message?: TermsOfUseModalMessage) => {
onClose={(message?: ConfirmModalMessage) => {
onReject(message ?? false);
}}
/>

View file

@ -2,13 +2,11 @@ import { useContext } from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { create } from 'react-modal-promise';
import { WebModal, MobileModal } from '@/components/ConfirmModal';
import { WebModal, MobileModal, modalPromisify } from '@/components/ConfirmModal';
import TextLink from '@/components/TextLink';
import { PageContext } from '@/hooks/use-page-context';
import usePlatform from '@/hooks/use-platform';
import { TermsOfUseModalMessage } from '@/types';
import { modalPromisify } from '../termsOfUseModalPromisify';
import { ConfirmModalMessage } from '@/types';
/**
* For web use only confirm modal, does not contain Terms iframe
@ -17,7 +15,7 @@ import { modalPromisify } from '../termsOfUseModalPromisify';
type Props = {
isOpen?: boolean;
onConfirm: () => void;
onClose: (message?: TermsOfUseModalMessage) => void;
onClose: (message?: ConfirmModalMessage) => void;
};
const TermsOfUseConfirmModal = ({ isOpen = false, onConfirm, onClose }: Props) => {
@ -33,7 +31,7 @@ const TermsOfUseConfirmModal = ({ isOpen = false, onConfirm, onClose }: Props) =
const linkProps = isMobile
? {
onClick: () => {
onClose(TermsOfUseModalMessage.SHOW_DETAIL_MODAL);
onClose(ConfirmModalMessage.SHOW_TERMS_DETAIL_MODAL);
},
}
: {

View file

@ -1,11 +1,9 @@
import { useContext } from 'react';
import { create } from 'react-modal-promise';
import { IframeModal } from '@/components/ConfirmModal';
import { IframeModal, modalPromisify } from '@/components/ConfirmModal';
import { PageContext } from '@/hooks/use-page-context';
import { modalPromisify } from '../termsOfUseModalPromisify';
/**
* For mobile use only, includes embedded Terms iframe
*/

View file

@ -6,7 +6,7 @@ import SettingsProvider from '@/__mocks__/RenderWithPageContext/SettingsProvider
import { signInBasic } from '@/apis/sign-in';
import { termsOfUseConfirmModalPromise } from '@/containers/TermsOfUse/TermsOfUseConfirmModal';
import { termsOfUseIframeModalPromise } from '@/containers/TermsOfUse/TermsOfUseIframeModal';
import { TermsOfUseModalMessage } from '@/types';
import { ConfirmModalMessage } from '@/types';
import UsernameSignIn from '.';
@ -98,7 +98,9 @@ describe('<UsernameSignIn>', () => {
});
test('should show terms detail modal', async () => {
termsOfUseConfirmModalPromiseMock.mockRejectedValue(TermsOfUseModalMessage.SHOW_DETAIL_MODAL);
termsOfUseConfirmModalPromiseMock.mockRejectedValue(
ConfirmModalMessage.SHOW_TERMS_DETAIL_MODAL
);
const { getByText, container } = renderWithPageContext(
<SettingsProvider>

View file

@ -2,7 +2,8 @@ import { useContext, useCallback } from 'react';
import { termsOfUseConfirmModalPromise } from '@/containers/TermsOfUse/TermsOfUseConfirmModal';
import { termsOfUseIframeModalPromise } from '@/containers/TermsOfUse/TermsOfUseIframeModal';
import { TermsOfUseModalMessage } from '@/types';
import { ConfirmModalMessage } from '@/types';
import { flattenPromiseResult } from '@/utils/promisify';
import { PageContext } from './use-page-context';
@ -12,29 +13,21 @@ const useTerms = () => {
const { termsOfUse } = experienceSettings ?? {};
const termsOfUseIframeModalHandler = useCallback(async () => {
try {
await termsOfUseIframeModalPromise();
const [result] = await flattenPromiseResult<boolean>(termsOfUseIframeModalPromise());
return true;
} catch {
return false;
}
return Boolean(result);
}, []);
const termsOfUseConfirmModalHandler = useCallback(async () => {
try {
await termsOfUseConfirmModalPromise();
const [result, error] = await flattenPromiseResult<boolean>(termsOfUseConfirmModalPromise());
return true;
} catch (error: unknown) {
if (error === TermsOfUseModalMessage.SHOW_DETAIL_MODAL) {
const result = await termsOfUseIframeModalHandler();
if (error === ConfirmModalMessage.SHOW_TERMS_DETAIL_MODAL) {
const result = await termsOfUseIframeModalHandler();
return result;
}
return false;
return result;
}
return Boolean(result);
}, [termsOfUseIframeModalHandler]);
const termsValidation = useCallback(async () => {

View file

@ -28,8 +28,8 @@ export type SignInExperienceSettings = Omit<
secondarySignInMethods: SignInMethod[];
};
export enum TermsOfUseModalMessage {
SHOW_DETAIL_MODAL = 'SHOW_DETAIL_MODAL',
export enum ConfirmModalMessage {
SHOW_TERMS_DETAIL_MODAL = 'SHOW_TERMS_DETAIL_MODAL',
}
export type PreviewConfig = {

View file

@ -0,0 +1,18 @@
import { flattenPromiseResult } from './promisify';
describe('promisify', () => {
test('flattenPromiseResult', async () => {
const promiseResolve = Promise.resolve('resolved');
const [result, rejection] = await flattenPromiseResult(promiseResolve);
expect(result).toBe('resolved');
expect(rejection).toBeUndefined();
// eslint-disable-next-line prefer-promise-reject-errors
const promiseRejection = Promise.reject('rejected');
const [_result, _rejection] = await flattenPromiseResult(promiseRejection);
expect(_result).toBeUndefined();
expect(_rejection).toBe('rejected');
});
});

View file

@ -0,0 +1,9 @@
export const flattenPromiseResult = async <T>(promise: Promise<T>): Promise<[T?, unknown?]> => {
try {
const result = await promise;
return [result];
} catch (error: unknown) {
return [undefined, error];
}
};