I am building a React JS application using TypeScript. In my application, I am using TinyMCE editor in a form. I am also writing integration tests using Cypress in TypeScript. I am now having trouble setting the TinyMCE editor value in the Cypress using TypeScript. I am using this library to manipulate TinyMCE editor in Cypress, https://github.com/ForeachOS/cypress-tinymce.
This is my React JS TinyMCE editor code.
import React, { FC } from 'react'
import { Editor } from '@tinymce/tinymce-react'
interface RichEditorFieldProps {
id: string
name?: string
value?: string
onChange: (fieldName: string, value: string) => void
}
const RichEditorField: FC<RichEditorFieldProps> = (
props: RichEditorFieldProps
) => {
const getFieldName = () => {
return props.name ? props.name : props.id
}
return (
<div cy-data-id={props.id} className={'rich-editor-field-container'}>
<Editor
id={props.id}
apiKey={'zjf0nctg4gmjj0a5u5uxm7pcrs0ka4hwcuxzskhxh5hauugf'}
value={props.value ?? ''}
onEditorChange={(content) => {
props.onChange(getFieldName(), content)
}}
/>
</div>
)
}
I am rendering that component as follows:
<FormRichEditorField
value={formik.values.specification}
label={'Specification'}
error={
formik.touched.specification &&
formik.errors.specification
}
id={'specification'}
onChange={formik.setFieldValue}
/>
What I want to highlight is that the id of the editor is specification
.
To write the test for that in Cypress, I installed the package I mentioned, https://github.com/ForeachOS/cypress-tinymce.
After I installed the package and import it into support/index.ts file, I cannot just call the function as follows:
cy.setTinyMceContent('specification', 'This is the new content');
I have to add the following code to make it compatible with TypeScript:
declare namespace Cypress {
interface Chainable<Subject = any> {
setTinyMceContent(tinyMceId: string, content: any): void
}
}
Then I set the value of the TinyMCE editor field as follow in my Cypress test:
cy.setTinyMceContent('specification', 'This is testing')
When I run the test, I am getting the following error:
Cannot read properties of undefined (reading 'specification')
What is wrong with my code and how can I fix it?
The package cypress-tinymce
looks well out of date. There's no editors
property on the latest ver 6 tinyMCE.
The following is the best I have so far. There are a couple of places where you need to wait for the editor to spin up.
The 2nd waits for current text content, which isn't good as it's too specific. I haven't found a better way to do this yet.
Updated from @WaiYanHein comment
/// <reference types="cypress" />
Cypress.Commands.add('setTinyMceContent', (tinyMceId: string, content: any) => {
cy.window().should('have.property', 'tinymce') // wait for tinyMCE
cy.wait(1000).then(() => { // wait for editor to be ready
const win = cy.state('window')
const editor = win.tinymce.EditorManager.get()
.filter((editor: any) => editor.id === fieldId)[0]
editor2.setContent(content, { format: 'text' });
})
})
it('adds some text to tinyMCE', () => {
cy.visit('http://localhost:3001')
cy.setTinyMceContent('specification', 'This is the new content')
cy.window().then(win => {
cy.wrap(win.tinymce.activeEditor.getContent({ format: 'text'}))
.should('eq', 'This is the new content') // ✅ passes
})
});
The React app is controlling the content, you may see the text change to "This is the new content" then revert to "Some text".
I think this is caused by the onChange()
event firing which re-renders the component and sets it back to the App's text.
Because of that, it may be better to control the React app through app actions rather than approach the tinyMCE API directly. Depends on the goals of your testing.