fix(angular, react, vue): overlays no longer throw errors when used inside tests (#24681)

resolves #24549, resolves #24590
This commit is contained in:
Liam DeBeasi
2022-02-02 15:25:51 -05:00
committed by GitHub
parent b0c9f097d2
commit 897ae4a454
12 changed files with 94 additions and 74 deletions

View File

@ -12,7 +12,8 @@ interface OverlayBase extends HTMLElement {
export function useController<OptionsType, OverlayType extends OverlayBase>(
displayName: string,
controller: { create: (options: OptionsType) => Promise<OverlayType> }
controller: { create: (options: OptionsType) => Promise<OverlayType> },
defineCustomElement: () => void
) {
const overlayRef = useRef<OverlayType>();
const didDismissEventName = useMemo(() => `on${displayName}DidDismiss`, [displayName]);
@ -20,11 +21,14 @@ export function useController<OptionsType, OverlayType extends OverlayBase>(
const willDismissEventName = useMemo(() => `on${displayName}WillDismiss`, [displayName]);
const willPresentEventName = useMemo(() => `on${displayName}WillPresent`, [displayName]);
defineCustomElement();
const present = useCallback(
async (options: OptionsType & HookOverlayOptions) => {
if (overlayRef.current) {
return;
}
const { onDidDismiss, onWillDismiss, onDidPresent, onWillPresent, ...rest } = options;
const handleDismiss = (event: CustomEvent<OverlayEventDetail<any>>) => {

View File

@ -1,4 +1,5 @@
import { ActionSheetButton, ActionSheetOptions, actionSheetController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-action-sheet.js';
import { useCallback } from 'react';
import { HookOverlayOptions } from './HookOverlayOptions';
@ -11,7 +12,8 @@ import { useController } from './useController';
export function useIonActionSheet(): UseIonActionSheetResult {
const controller = useController<ActionSheetOptions, HTMLIonActionSheetElement>(
'IonActionSheet',
actionSheetController
actionSheetController,
defineCustomElement
);
const present = useCallback(

View File

@ -1,4 +1,5 @@
import { AlertButton, AlertOptions, alertController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-alert.js';
import { useCallback } from 'react';
import { HookOverlayOptions } from './HookOverlayOptions';
@ -9,7 +10,7 @@ import { useController } from './useController';
* @returns Returns the present and dismiss methods in an array
*/
export function useIonAlert(): UseIonAlertResult {
const controller = useController<AlertOptions, HTMLIonAlertElement>('IonAlert', alertController);
const controller = useController<AlertOptions, HTMLIonAlertElement>('IonAlert', alertController, defineCustomElement);
const present = useCallback(
(messageOrOptions: string | (AlertOptions & HookOverlayOptions), buttons?: AlertButton[]) => {

View File

@ -1,4 +1,5 @@
import { LoadingOptions, SpinnerTypes, loadingController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-loading.js';
import { useCallback } from 'react';
import { HookOverlayOptions } from './HookOverlayOptions';
@ -11,7 +12,8 @@ import { useController } from './useController';
export function useIonLoading(): UseIonLoadingResult {
const controller = useController<LoadingOptions, HTMLIonLoadingElement>(
'IonLoading',
loadingController
loadingController,
defineCustomElement
);
const present = useCallback(

View File

@ -1,4 +1,5 @@
import { ModalOptions, modalController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';
import { useCallback } from 'react';
import { ReactComponentOrElement } from '../models/ReactComponentOrElement';
@ -19,6 +20,7 @@ export function useIonModal(
const controller = useOverlay<ModalOptions, HTMLIonModalElement>(
'IonModal',
modalController,
defineCustomElement,
component,
componentProps
);

View File

@ -4,6 +4,7 @@ import {
PickerOptions,
pickerController,
} from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-picker.js';
import { useCallback } from 'react';
import { HookOverlayOptions } from './HookOverlayOptions';
@ -16,7 +17,8 @@ import { useController } from './useController';
export function useIonPicker(): UseIonPickerResult {
const controller = useController<PickerOptions, HTMLIonPickerElement>(
'IonPicker',
pickerController
pickerController,
defineCustomElement
);
const present = useCallback((

View File

@ -1,4 +1,5 @@
import { PopoverOptions, popoverController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-popover.js';
import { useCallback } from 'react';
import { ReactComponentOrElement } from '../models/ReactComponentOrElement';
@ -16,6 +17,7 @@ export function useIonPopover(component: ReactComponentOrElement, componentProps
const controller = useOverlay<PopoverOptions, HTMLIonPopoverElement>(
'IonPopover',
popoverController,
defineCustomElement,
component,
componentProps
);

View File

@ -1,4 +1,5 @@
import { ToastOptions, toastController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-toast.js';
import { useCallback } from 'react';
import { HookOverlayOptions } from './HookOverlayOptions';
@ -11,7 +12,8 @@ import { useController } from './useController';
export function useIonToast(): UseIonToastResult {
const controller = useController<ToastOptions, HTMLIonToastElement>(
'IonToast',
toastController
toastController,
defineCustomElement
);
const present = useCallback((messageOrOptions: string | ToastOptions & HookOverlayOptions, duration?: number) => {

View File

@ -16,6 +16,7 @@ interface OverlayBase extends HTMLElement {
export function useOverlay<OptionsType, OverlayType extends OverlayBase>(
displayName: string,
controller: { create: (options: OptionsType) => Promise<OverlayType> },
defineCustomElement: () => void,
component: ReactComponentOrElement,
componentProps?: any
) {
@ -29,6 +30,8 @@ export function useOverlay<OptionsType, OverlayType extends OverlayBase>(
const ionContext = useContext(IonContext);
const [overlayId] = useState(generateId('overlay'));
defineCustomElement();
useEffect(() => {
if (isOpen && component && containerElRef.current) {
if (React.isValidElement(component)) {