-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
286 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import { CK_CDN_URL, INJECTED_SCRIPTS, INJECTED_STYLESHEETS } from '@ckeditor/ckeditor5-integrations-common'; | ||
|
||
export const removeCkCdnScripts = (): void => { | ||
[ ...document.querySelectorAll( 'script' ) ] | ||
.filter( script => script.src.startsWith( CK_CDN_URL ) ) | ||
.forEach( script => { | ||
INJECTED_SCRIPTS.delete( script.src ); | ||
script.remove(); | ||
} ); | ||
|
||
// Clear the CKEditor global variables | ||
delete window.CKEDITOR; | ||
delete window.CKEDITOR_PREMIUM_FEATURES; | ||
window.CKEDITOR_VERSION = ''; | ||
}; | ||
|
||
/** | ||
* Removes all CKEditor stylesheets and preloads from the DOM. | ||
*/ | ||
export const removeCkCdnLinks = (): void => { | ||
[ ...document.querySelectorAll( 'link' ) ] | ||
.filter( link => link.href.startsWith( CK_CDN_URL ) ) | ||
.forEach( link => { | ||
INJECTED_STYLESHEETS.delete( link.href ); | ||
link.remove(); | ||
} ); | ||
}; | ||
|
||
/** | ||
* Removes all CKEditor scripts and stylesheets from the DOM. | ||
*/ | ||
export const removeInjectedCdnStuff = (): void => { | ||
removeCkCdnScripts(); | ||
removeCkCdnLinks(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import { beforeEach, describe, expect, it } from 'vitest'; | ||
import { renderHook, waitFor, act } from '@testing-library/react'; | ||
|
||
import type { CKEditorCloudConfig } from '@ckeditor/ckeditor5-integrations-common'; | ||
|
||
import { removeInjectedCdnStuff } from '../_utils/cloud'; | ||
import useCKEditorCloud from '../../src/cloud/useCKEditorCloud'; | ||
|
||
describe( 'useCKEditorCloud', () => { | ||
beforeEach( removeInjectedCdnStuff ); | ||
|
||
it( 'should load CKEditor bundles from CDN', async () => { | ||
const { result } = renderHook( () => useCKEditorCloud( { | ||
version: '43.0.0', | ||
languages: [ 'en', 'de' ] | ||
} ) ); | ||
|
||
expect( result.current.status ).toBe( 'loading' ); | ||
|
||
await waitFor( () => { | ||
expect( result.current.status ).toBe( 'success' ); | ||
|
||
if ( result.current.status === 'success' ) { | ||
expect( result.current.CKEditor ).toBeDefined(); | ||
} | ||
} ); | ||
} ); | ||
|
||
it( 'should load additional bundle after updating deps', async () => { | ||
const { result, rerender } = renderHook( | ||
( config: CKEditorCloudConfig<any> ) => useCKEditorCloud( config ), | ||
{ | ||
initialProps: { | ||
version: '43.0.0', | ||
withPremiumFeatures: false | ||
} | ||
} | ||
); | ||
|
||
await waitFor( () => { | ||
expect( result.current.status ).toBe( 'success' ); | ||
|
||
if ( result.current.status === 'success' ) { | ||
expect( result.current.CKEditor ).toBeDefined(); | ||
expect( result.current.CKEditorPremiumFeatures ).toBeUndefined(); | ||
} | ||
} ); | ||
|
||
rerender( { | ||
version: '43.0.0', | ||
withPremiumFeatures: true | ||
} ); | ||
|
||
act( () => { | ||
expect( result.current.status ).toBe( 'loading' ); | ||
} ); | ||
|
||
await waitFor( () => { | ||
expect( result.current.status ).toBe( 'success' ); | ||
|
||
if ( result.current.status === 'success' ) { | ||
expect( result.current.CKEditor ).toBeDefined(); | ||
expect( result.current.CKEditorPremiumFeatures ).toBeDefined(); | ||
} | ||
} ); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import React, { type MutableRefObject } from 'react'; | ||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'; | ||
import { cleanup, render } from '@testing-library/react'; | ||
import { createDefer } from '@ckeditor/ckeditor5-integrations-common'; | ||
|
||
import { removeInjectedCdnStuff } from '../_utils/cloud'; | ||
import withCKEditorCloud, { type WithCKEditorCloudHocProps } from '../../src/cloud/withCKEditorCloud'; | ||
|
||
describe( 'withCKEditorCloud', () => { | ||
const lastRenderedMockProps: MutableRefObject<WithCKEditorCloudHocProps | null> = { | ||
current: null | ||
}; | ||
|
||
afterEach( cleanup ); | ||
|
||
beforeEach( () => { | ||
removeInjectedCdnStuff(); | ||
lastRenderedMockProps.current = null; | ||
} ); | ||
|
||
const MockComponent = ( props: WithCKEditorCloudHocProps & { editorId: number } ) => { | ||
lastRenderedMockProps.current = { ...props }; | ||
|
||
return ( | ||
<div> | ||
Your Editor { props.editorId } | ||
</div> | ||
); | ||
}; | ||
|
||
it( 'should inject cloud integration to the wrapped component', async () => { | ||
const WrappedComponent = withCKEditorCloud( { | ||
cloud: { | ||
version: '43.0.0' | ||
} | ||
} )( MockComponent ); | ||
|
||
const { findByText } = render( <WrappedComponent editorId={ 1 } /> ); | ||
|
||
expect( await findByText( 'Your Editor 1' ) ).toBeVisible(); | ||
expect( lastRenderedMockProps.current ).toMatchObject( { | ||
editorId: 1, | ||
cloud: expect.objectContaining( { | ||
CKEditor: expect.objectContaining( { | ||
ClassicEditor: expect.any( Function ) | ||
} ) | ||
} ) | ||
} ); | ||
} ); | ||
|
||
it( 'should show loading spinner when cloud is not ready', async () => { | ||
const deferredPlugin = createDefer<number>(); | ||
const WrappedComponent = withCKEditorCloud( { | ||
renderLoader: () => <div>Loading...</div>, | ||
cloud: { | ||
version: '43.0.0', | ||
plugins: { | ||
Plugin: { | ||
getExportedEntries: () => deferredPlugin.promise | ||
} | ||
} | ||
} | ||
} )( MockComponent ); | ||
|
||
const { findByText } = render( <WrappedComponent editorId={ 1 } /> ); | ||
|
||
expect( await findByText( 'Loading...' ) ).toBeVisible(); | ||
|
||
deferredPlugin.resolve( 123 ); | ||
|
||
expect( await findByText( 'Your Editor 1' ) ).toBeVisible(); | ||
expect( lastRenderedMockProps.current?.cloud.CKPlugins?.Plugin ).toBe( 123 ); | ||
} ); | ||
|
||
it( 'should show error message when cloud loading fails', async () => { | ||
const WrappedComponent = withCKEditorCloud( { | ||
renderError: error => <div>Error: { error.message }</div>, | ||
cloud: { | ||
version: '43.0.0', | ||
plugins: { | ||
Plugin: { | ||
getExportedEntries: () => { | ||
throw new Error( 'Failed to load plugin' ); | ||
} | ||
} | ||
} | ||
} | ||
} )( MockComponent ); | ||
|
||
const { findByText } = render( <WrappedComponent editorId={ 1 } /> ); | ||
|
||
expect( await findByText( 'Error: Failed to load plugin' ) ).toBeVisible(); | ||
} ); | ||
|
||
it( 'should render default error message when cloud loading fails and there is no error handler specified', async () => { | ||
const WrappedComponent = withCKEditorCloud( { | ||
cloud: { | ||
version: '43.0.0', | ||
plugins: { | ||
Plugin: { | ||
getExportedEntries: () => { | ||
throw new Error( 'Failed to load plugin' ); | ||
} | ||
} | ||
} | ||
} | ||
} )( MockComponent ); | ||
|
||
const { findByText } = render( <WrappedComponent editorId={ 1 } /> ); | ||
|
||
expect( await findByText( 'Unable to load CKEditor Cloud data!' ) ).toBeVisible(); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import '@testing-library/jest-dom/vitest'; |
Oops, something went wrong.