diff --git a/src/generic/hooks/tests/hooks.test.tsx b/src/generic/hooks/tests/hooks.test.tsx index d2e83f06f..ef1bbb303 100644 --- a/src/generic/hooks/tests/hooks.test.tsx +++ b/src/generic/hooks/tests/hooks.test.tsx @@ -1,18 +1,13 @@ import React from 'react'; import { getConfig } from '@edx/frontend-platform'; import { act, renderHook } from '@testing-library/react'; -import { useKeyedState } from '@edx/react-unit-test-utils'; import { logError } from '@edx/frontend-platform/logging'; -import { iframeMessageTypes, iframeStateKeys } from '../../../constants'; -import { useIframeBehavior } from '../useIframeBehavior'; +import { iframeMessageTypes } from '../../../constants'; +import { useIframeBehavior, iframeBehaviorState } from '../useIframeBehavior'; import { useLoadBearingHook } from '../useLoadBearingHook'; jest.useFakeTimers(); -jest.mock('@edx/react-unit-test-utils', () => ({ - useKeyedState: jest.fn(), -})); - jest.mock('@edx/frontend-platform/logging', () => ({ logError: jest.fn(), })); @@ -27,20 +22,10 @@ describe('useIframeBehavior', () => { const iframeRef = { current: { contentWindow: null } as HTMLIFrameElement }; beforeEach(() => { - (useKeyedState as jest.Mock).mockImplementation((key, initialValue) => { - switch (key) { - case iframeStateKeys.iframeHeight: - return [0, setIframeHeight]; - case iframeStateKeys.hasLoaded: - return [false, setHasLoaded]; - case iframeStateKeys.showError: - return [false, setShowError]; - case iframeStateKeys.windowTopOffset: - return [null, setWindowTopOffset]; - default: - return [initialValue, jest.fn()]; - } - }); + jest.spyOn(iframeBehaviorState, 'iframeHeight').mockImplementation(() => [0, setIframeHeight]); + jest.spyOn(iframeBehaviorState, 'hasLoaded').mockImplementation(() => [false, setHasLoaded]); + jest.spyOn(iframeBehaviorState, 'showError').mockImplementation(() => [false, setShowError]); + jest.spyOn(iframeBehaviorState, 'windowTopOffset').mockImplementation(() => [null, setWindowTopOffset]); window.scrollTo = jest.fn((x: number | ScrollToOptions, y?: number): void => { const scrollY = typeof x === 'number' ? y : (x as ScrollToOptions).top || 0; @@ -58,14 +43,7 @@ describe('useIframeBehavior', () => { it('scrolls to previous position on video fullscreen exit', () => { const mockWindowTopOffset = 100; - - (useKeyedState as jest.Mock).mockImplementation((key) => { - if (key === iframeStateKeys.windowTopOffset) { - return [mockWindowTopOffset, setWindowTopOffset]; - } - return [null, jest.fn()]; - }); - + jest.spyOn(iframeBehaviorState, 'windowTopOffset').mockImplementation(() => [mockWindowTopOffset, setWindowTopOffset]); renderHook(() => useIframeBehavior({ id, iframeUrl, iframeRef })); const message = { diff --git a/src/generic/hooks/useIframeBehavior.tsx b/src/generic/hooks/useIframeBehavior.tsx index 1e60a6f94..7d50d1e0f 100644 --- a/src/generic/hooks/useIframeBehavior.tsx +++ b/src/generic/hooks/useIframeBehavior.tsx @@ -1,13 +1,24 @@ -import { useCallback, useEffect } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { logError } from '@edx/frontend-platform/logging'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { useKeyedState } from '@edx/react-unit-test-utils'; - +import StrictDict from '@src/editors/utils/StrictDict'; import { useLoadBearingHook } from './useLoadBearingHook'; -import { iframeStateKeys, iframeMessageTypes } from '../../constants'; +import { iframeMessageTypes } from '../../constants'; import { UseIFrameBehaviorReturnTypes, UseIFrameBehaviorTypes } from '../types'; import { useEventListener } from './useEventListener'; +/** + * Internal state hooks for useIFrameBehavior. + * Defined and exported here so they can be mocked/manipulated in tests. + */ +export const iframeBehaviorState = StrictDict({ + /* eslint-disable react-hooks/rules-of-hooks */ + iframeHeight: (val) => useState(val), + hasLoaded: (val) => useState(val), + showError: (val) => useState(val), + windowTopOffset: (val) => useState(val), + /* eslint-enable react-hooks/rules-of-hooks */ +}); + /** * Custom hook to manage iframe behavior. * @@ -31,10 +42,10 @@ export const useIframeBehavior = ({ // Do not remove this hook. See function description. useLoadBearingHook(id); - const [iframeHeight, setIframeHeight] = useKeyedState(iframeStateKeys.iframeHeight, 0); - const [hasLoaded, setHasLoaded] = useKeyedState(iframeStateKeys.hasLoaded, false); - const [showError, setShowError] = useKeyedState(iframeStateKeys.showError, false); - const [windowTopOffset, setWindowTopOffset] = useKeyedState(iframeStateKeys.windowTopOffset, null); + const [iframeHeight, setIframeHeight] = iframeBehaviorState.iframeHeight(0); + const [hasLoaded, setHasLoaded] = iframeBehaviorState.hasLoaded(false); + const [showError, setShowError] = iframeBehaviorState.showError(false); + const [windowTopOffset, setWindowTopOffset] = iframeBehaviorState.windowTopOffset(null); const receiveMessage = useCallback((event: MessageEvent) => { if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {