From 7ee9652871da6dd7b93824982801852dfbc288fa Mon Sep 17 00:00:00 2001 From: Mateusz Baginski Date: Mon, 30 Sep 2024 07:29:00 +0200 Subject: [PATCH 1/3] Fix incorrect arguments typings in `useAsyncValue` and `useAsyncCallback` hooks --- src/hooks/useAsyncCallback.ts | 6 +++--- src/hooks/useAsyncValue.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useAsyncCallback.ts b/src/hooks/useAsyncCallback.ts index c962493..988fa26 100644 --- a/src/hooks/useAsyncCallback.ts +++ b/src/hooks/useAsyncCallback.ts @@ -34,7 +34,7 @@ import { useRefSafeCallback } from './useRefSafeCallback.js'; * ``` */ export const useAsyncCallback = , R>( - callback: ( ...args: Array ) => Promise + callback: ( ...args: A ) => Promise ): AsyncCallbackHookResult => { // The state of the asynchronous callback. const [ asyncState, setAsyncState ] = useState>( { @@ -50,7 +50,7 @@ export const useAsyncCallback = , R>( const prevExecutionUIDRef = useRef( null ); // The asynchronous executor function, which is a wrapped version of the original callback. - const asyncExecutor = useRefSafeCallback( async ( ...args: Array ) => { + const asyncExecutor = useRefSafeCallback( async ( ...args: A ) => { if ( unmountedRef.current || isSSR() ) { return null; } @@ -101,7 +101,7 @@ export const useAsyncCallback = , R>( * Represents the result of the `useAsyncCallback` hook. */ export type AsyncCallbackHookResult, R> = [ - ( ...args: Array ) => Promise, + ( ...args: A ) => Promise, AsyncCallbackState ]; diff --git a/src/hooks/useAsyncValue.ts b/src/hooks/useAsyncValue.ts index 39f8b17..a71b836 100644 --- a/src/hooks/useAsyncValue.ts +++ b/src/hooks/useAsyncValue.ts @@ -38,7 +38,7 @@ import { useAsyncCallback, type AsyncCallbackState } from './useAsyncCallback.js * ``` */ export const useAsyncValue = , R>( - callback: ( ...args: Array ) => Promise, + callback: ( ...args: A ) => Promise, deps: DependencyList ): AsyncValueHookResult => { const [ asyncCallback, asyncState ] = useAsyncCallback( callback ); From 4bba08edebb84fa94eae0b56891ec67d413e7796 Mon Sep 17 00:00:00 2001 From: Mateusz Baginski Date: Mon, 30 Sep 2024 07:29:28 +0200 Subject: [PATCH 2/3] Fix different behavior of `useInstantEffect` on `Vite` and `Next` --- src/hooks/useInstantEffect.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useInstantEffect.ts b/src/hooks/useInstantEffect.ts index 3f20802..6f01875 100644 --- a/src/hooks/useInstantEffect.ts +++ b/src/hooks/useInstantEffect.ts @@ -3,7 +3,7 @@ * For licensing, see LICENSE.md. */ -import { useRef, type DependencyList } from 'react'; +import { useState, type DependencyList } from 'react'; import { shallowCompareArrays } from '@ckeditor/ckeditor5-integrations-common'; /** @@ -13,10 +13,10 @@ import { shallowCompareArrays } from '@ckeditor/ckeditor5-integrations-common'; * @param deps The dependency list. */ export const useInstantEffect = ( fn: VoidFunction, deps: DependencyList ): void => { - const prevDeps = useRef( null ); + const [ prevDeps, setDeps ] = useState( null ); - if ( !shallowCompareArrays( prevDeps.current, deps ) ) { - prevDeps.current = [ ...deps ]; + if ( !shallowCompareArrays( prevDeps, deps ) ) { fn(); + setDeps( [ ...deps ] ); } }; From bd261f1e0e1de489a7fae4a5528eb659e329c9b5 Mon Sep 17 00:00:00 2001 From: Mateusz Baginski Date: Mon, 30 Sep 2024 07:29:42 +0200 Subject: [PATCH 3/3] Add cleanup methods to few tests --- tests/cloud/useCKEditorCloud.test.tsx | 9 ++++++--- tests/cloud/withCKEditorCloud.test.tsx | 7 +++---- tests/hooks/useAsyncCallback.test.tsx | 6 ++++-- tests/hooks/useAsyncValue.test.tsx | 6 ++++-- tests/hooks/useInstantEditorEffect.test.tsx | 6 ++++-- tests/hooks/useInstantEffect.test.tsx | 6 ++++-- tests/hooks/useIsMountedRef.test.tsx | 6 ++++-- tests/hooks/useIsUnmountedRef.test.tsx | 6 ++++-- tests/hooks/useRefSafeCallback.test.tsx | 6 ++++-- 9 files changed, 37 insertions(+), 21 deletions(-) diff --git a/tests/cloud/useCKEditorCloud.test.tsx b/tests/cloud/useCKEditorCloud.test.tsx index fd0f92a..bdd7ac1 100644 --- a/tests/cloud/useCKEditorCloud.test.tsx +++ b/tests/cloud/useCKEditorCloud.test.tsx @@ -3,8 +3,8 @@ * For licensing, see LICENSE.md. */ -import { beforeEach, describe, expect, expectTypeOf, it } from 'vitest'; -import { renderHook, waitFor, act } from '@testing-library/react'; +import { afterEach, describe, expect, expectTypeOf, it } from 'vitest'; +import { renderHook, waitFor, act, cleanup } from '@testing-library/react'; import type { CKEditorCloudConfig } from '@ckeditor/ckeditor5-integrations-common'; import { removeAllCkCdnResources } from '@ckeditor/ckeditor5-integrations-common/test-utils'; @@ -12,7 +12,10 @@ import { removeAllCkCdnResources } from '@ckeditor/ckeditor5-integrations-common import useCKEditorCloud from '../../src/cloud/useCKEditorCloud.js'; describe( 'useCKEditorCloud', () => { - beforeEach( removeAllCkCdnResources ); + afterEach( () => { + cleanup(); + removeAllCkCdnResources(); + } ); it( 'should load CKEditor bundles from CDN', async () => { const { result } = renderHook( () => useCKEditorCloud( { diff --git a/tests/cloud/withCKEditorCloud.test.tsx b/tests/cloud/withCKEditorCloud.test.tsx index 594bf74..bb9d992 100644 --- a/tests/cloud/withCKEditorCloud.test.tsx +++ b/tests/cloud/withCKEditorCloud.test.tsx @@ -4,7 +4,7 @@ */ import React, { type MutableRefObject } from 'react'; -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { afterEach, describe, expect, it } from 'vitest'; import { cleanup, render } from '@testing-library/react'; import { createDefer } from '@ckeditor/ckeditor5-integrations-common'; @@ -17,9 +17,8 @@ describe( 'withCKEditorCloud', () => { current: null }; - afterEach( cleanup ); - - beforeEach( () => { + afterEach( () => { + cleanup(); removeAllCkCdnResources(); lastRenderedMockProps.current = null; } ); diff --git a/tests/hooks/useAsyncCallback.test.tsx b/tests/hooks/useAsyncCallback.test.tsx index 44678d5..bd8ff77 100644 --- a/tests/hooks/useAsyncCallback.test.tsx +++ b/tests/hooks/useAsyncCallback.test.tsx @@ -3,12 +3,14 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it, vi } from 'vitest'; -import { renderHook, act, waitFor } from '@testing-library/react'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { renderHook, act, waitFor, cleanup } from '@testing-library/react'; import { useAsyncCallback } from '../../src/hooks/useAsyncCallback.js'; import { timeout } from '../_utils/timeout.js'; describe( 'useAsyncCallback', () => { + afterEach( cleanup ); + it( 'should execute the callback and update the state correctly when the callback resolves', async () => { const fetchData = vi.fn().mockResolvedValue( 'data' ); diff --git a/tests/hooks/useAsyncValue.test.tsx b/tests/hooks/useAsyncValue.test.tsx index f90af4a..fefeae6 100644 --- a/tests/hooks/useAsyncValue.test.tsx +++ b/tests/hooks/useAsyncValue.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it } from 'vitest'; -import { renderHook, waitFor } from '@testing-library/react'; +import { afterEach, describe, expect, it } from 'vitest'; +import { cleanup, renderHook, waitFor } from '@testing-library/react'; import { useAsyncValue } from '../../src/hooks/useAsyncValue.js'; describe( 'useAsyncValue', () => { + afterEach( cleanup ); + it( 'should return a mutable ref object', async () => { const { result } = renderHook( () => useAsyncValue( async () => 123, [] ) ); diff --git a/tests/hooks/useInstantEditorEffect.test.tsx b/tests/hooks/useInstantEditorEffect.test.tsx index b106b75..f219e80 100644 --- a/tests/hooks/useInstantEditorEffect.test.tsx +++ b/tests/hooks/useInstantEditorEffect.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it, vi } from 'vitest'; -import { renderHook } from '@testing-library/react'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { cleanup, renderHook } from '@testing-library/react'; import { useInstantEditorEffect } from '../../src/hooks/useInstantEditorEffect.js'; describe( 'useInstantEditorEffect', () => { + afterEach( cleanup ); + it( 'should execute the provided function after mounting of editor', () => { const semaphore = { runAfterMount: vi.fn() diff --git a/tests/hooks/useInstantEffect.test.tsx b/tests/hooks/useInstantEffect.test.tsx index f808a41..8ca8056 100644 --- a/tests/hooks/useInstantEffect.test.tsx +++ b/tests/hooks/useInstantEffect.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it, vi } from 'vitest'; -import { renderHook } from '@testing-library/react'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { cleanup, renderHook } from '@testing-library/react'; import { useInstantEffect } from '../../src/hooks/useInstantEffect.js'; describe( 'useInstantEffect', () => { + afterEach( cleanup ); + it( 'should call the effect function when dependencies change', () => { const effectFn = vi.fn(); const { rerender } = renderHook( deps => useInstantEffect( effectFn, deps ), { diff --git a/tests/hooks/useIsMountedRef.test.tsx b/tests/hooks/useIsMountedRef.test.tsx index 87d8b1d..03e8968 100644 --- a/tests/hooks/useIsMountedRef.test.tsx +++ b/tests/hooks/useIsMountedRef.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it } from 'vitest'; -import { renderHook } from '@testing-library/react'; +import { afterEach, describe, expect, it } from 'vitest'; +import { cleanup, renderHook } from '@testing-library/react'; import { useIsMountedRef } from '../../src/hooks/useIsMountedRef.js'; describe( 'useIsMountedRef', () => { + afterEach( cleanup ); + it( 'should return a mutable ref object', () => { const { result } = renderHook( () => useIsMountedRef() ); diff --git a/tests/hooks/useIsUnmountedRef.test.tsx b/tests/hooks/useIsUnmountedRef.test.tsx index 087d98d..8369932 100644 --- a/tests/hooks/useIsUnmountedRef.test.tsx +++ b/tests/hooks/useIsUnmountedRef.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { describe, expect, it } from 'vitest'; -import { renderHook } from '@testing-library/react'; +import { afterEach, describe, expect, it } from 'vitest'; +import { cleanup, renderHook } from '@testing-library/react'; import { useIsUnmountedRef } from '../../src/hooks/useIsUnmountedRef.js'; describe( 'useIsUnmountedRef', () => { + afterEach( cleanup ); + it( 'should return a mutable ref object', () => { const { result } = renderHook( () => useIsUnmountedRef() ); diff --git a/tests/hooks/useRefSafeCallback.test.tsx b/tests/hooks/useRefSafeCallback.test.tsx index 3b8fa4a..ee8a322 100644 --- a/tests/hooks/useRefSafeCallback.test.tsx +++ b/tests/hooks/useRefSafeCallback.test.tsx @@ -3,11 +3,13 @@ * For licensing, see LICENSE.md. */ -import { expect, it, describe, vi } from 'vitest'; -import { renderHook, act } from '@testing-library/react'; +import { expect, it, describe, vi, afterEach } from 'vitest'; +import { renderHook, act, cleanup } from '@testing-library/react'; import { useRefSafeCallback } from '../../src/hooks/useRefSafeCallback.js'; describe( 'useRefSafeCallback', () => { + afterEach( cleanup ); + it( 'should return a function', () => { const { result } = renderHook( () => useRefSafeCallback( () => {} ) );