diff --git a/docs/getting-started/integrations/angular.md b/docs/getting-started/integrations/angular.md index 4b42b489b8f..ebab5a01772 100644 --- a/docs/getting-started/integrations/angular.md +++ b/docs/getting-started/integrations/angular.md @@ -696,6 +696,8 @@ There is a known issue related to the localization in Angular 17. Read more in t ## Known issues +### Module resolution + The `moduleResolution` option of the TypeScript configuration determines the algorithm for finding and resolving modules from `node_modules`. In Angular 17, the option is set to `node` by default. This option prevents type declaration for editor translations from being correctly loaded. To fix it, you have several options: * You can set the `moduleResolution` option to `bundler`. It is the recommended setting in TypeScript 5.0+ for applications that use a bundler. And it is a recommended way of fixing this problem. You can check other solutions below for lower TypeScript versions. @@ -703,6 +705,53 @@ The `moduleResolution` option of the TypeScript configuration determines the alg * You can update Angular to version 18, where the `moduleResolution` option is set to `bundler` by default. * You can import translations directly from our CDN, like: `import ‘https://cdn.ckeditor.com/ckeditor5/{@var ckeditor5-version}/translations/es.umd.js’;`. This way, the editor will load the translations automatically, so you do not need to pass them manually into the config. +### Jest testing + +You can use Jest as a test runner in Angular apps. Unfortunately, Jest does not use a real browser. Instead, it runs tests in Node.js that uses JSDOM. JSDOM is not a complete DOM implementation, and while it is sufficient for standard apps, it cannot polyfill all the DOM APIs that CKEditor 5 requires. + +For testing CKEditor 5, it is recommended to use testing frameworks that utilize a real browser and provide a complete DOM implementation. Some popular options include: + +* [Vitest](https://vitest.dev/) +* [Playwright](https://playwright.dev/) +* [Cypress](https://www.cypress.io/) + +These frameworks offer better support for testing CKEditor 5 and provide a more accurate representation of how the editor behaves in a real browser environment. + +If this is not possible and you still want to use Jest, you can mock some of the required APIs. Below is an example of how to mock some of the APIs used by CKEditor 5: + +```javascript +beforeAll( () => { + window.scrollTo = jest.fn(); + + window.ResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} + }; + + for ( const key of [ 'InputEvent', 'KeyboardEvent' ] ) { + window[ key ].prototype.getTargetRanges = () => { + const range = new StaticRange( { + startContainer: document.body.querySelector( '.ck-editor__editable p' ), + startOffset: 0, + endContainer: document.body.querySelector( '.ck-editor__editable p' ), + endOffset: 0 + } ); + + return [ range ]; + }; + } + + Range.prototype.getClientRects = () => ( { + item: () => null, + length: 0, + [ Symbol.iterator ]: function* () {} + } ); +} ); +``` + +These mocks should be placed before the tests that use CKEditor 5. They are imperfect and may not cover all the cases, but they should be sufficient for basic initialization and rendering editor. Keep in mind that they are not a replacement for proper browser testing. + ## Contributing and reporting issues The source code of the CKEditor 5 rich text editor component for Angular is available on GitHub in [https://github.com/ckeditor/ckeditor5-angular](https://github.com/ckeditor/ckeditor5-angular). diff --git a/docs/getting-started/integrations/react.md b/docs/getting-started/integrations/react.md index 66b7f3acdd1..8c07875a674 100644 --- a/docs/getting-started/integrations/react.md +++ b/docs/getting-started/integrations/react.md @@ -288,6 +288,106 @@ export default App; For more information, please refer to the {@link getting-started/setup/ui-language Setting the UI language} guide. +### Jest testing + +Jest is the default test runner used by many React apps. Unfortunately, Jest does not use a real browser. Instead, it runs tests in Node.js that uses JSDOM. JSDOM is not a complete DOM implementation, and while it is sufficient for standard apps, it cannot polyfill all the DOM APIs that CKEditor 5 requires. + +For testing CKEditor 5, it is recommended to use testing frameworks that utilize a real browser and provide a complete DOM implementation. Some popular options include: + +* [Vitest](https://vitest.dev/) +* [Playwright](https://playwright.dev/) +* [Cypress](https://www.cypress.io/) + +These frameworks offer better support for testing CKEditor 5 and provide a more accurate representation of how the editor behaves in a real browser environment. + +If this is not possible and you still want to use Jest, you can mock some of the required APIs. Below is an example of how to mock some of the APIs used by CKEditor 5: + +```jsx +import React, { useRef } from 'react'; +import { render, waitFor, screen } from '@testing-library/react'; +import { userEvent } from '@testing-library/user-event'; + +import { DecoupledEditor, Essentials, Paragraph } from 'ckeditor5'; +import { CKEditor } from '@ckeditor/ckeditor5-react'; + +beforeAll( () => { + window.scrollTo = jest.fn(); + + window.ResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} + }; + + for ( const key of [ 'InputEvent', 'KeyboardEvent' ] ) { + window[ key ].prototype.getTargetRanges = () => { + const range = new StaticRange( { + startContainer: document.body.querySelector( '.ck-editor__editable p' ), + startOffset: 0, + endContainer: document.body.querySelector( '.ck-editor__editable p' ), + endOffset: 0 + } ); + + return [ range ]; + }; + } + + Range.prototype.getClientRects = () => ( { + item: () => null, + length: 0, + [ Symbol.iterator ]: function* () {} + } ); +} ); + +const SomeComponent = ( { value, onChange } ) => { + const editorRef = useRef(); + + return ( +
+ { + editorRef.current = editor; + } } + data={ value } + onChange={ () => { + onChange( editorRef.current?.getData() ); + } } + /> +
+ ); +}; + +it( 'renders', async () => { + render( ); + + await waitFor( () => expect( screen.getByText( /some content/ ) ).toBeTruthy()); +} ); + +it( 'updates', async () => { + const onChange = jest.fn(); + render( ); + + await waitFor( () => expect( screen.getByText( /some content/ ) ).toBeTruthy() ); + + await userEvent.click( document.querySelector( '[contenteditable="true"]' ) ); + + userEvent.keyboard( 'more stuff' ); + + await waitFor( () => expect( onChange ).toHaveBeenCalled() ); +} ); +``` + +The mocks presented above only test two basic scenarios, and more will likely need to be added, which may change with each version of the editor. + ## Contributing and reporting issues The source code of rich text editor component for React is available on GitHub in [https://github.com/ckeditor/ckeditor5-react](https://github.com/ckeditor/ckeditor5-react). diff --git a/docs/getting-started/integrations/vuejs-v3.md b/docs/getting-started/integrations/vuejs-v3.md index 30d7b225589..46fd366c300 100644 --- a/docs/getting-started/integrations/vuejs-v3.md +++ b/docs/getting-started/integrations/vuejs-v3.md @@ -400,7 +400,7 @@ Since accessing the editor toolbar is not possible until after the editor instan