reactjs - @foreachbe/cypress-tinymce TinyMCE-paketet för Cypress returnerar alltid undefined för editors-instansen med TypeScript


Jag bygger en React JS-applikation med TypeScript. I min applikation använder jag TinyMCE-redigeraren i ett formulär. Jag skriver också integrationstester med Cypress i TypeScript. Jag har nu problem med att ställa in värdet i TinyMCE-redigeraren i Cypress med TypeScript. Jag använder detta bibliotek för att manipulera TinyMCE-redigeraren i Cypress, https://github.com/ForeachOS/cypress-tinymce.

Detta är min React JS TinyMCE-redigerarkod.

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>
    )
}

Jag renderar den komponenten på följande sätt:

<FormRichEditorField
                            value={formik.values.specification}
                            label={'Specification'}
                            error={
                                formik.touched.specification &&
                                formik.errors.specification
                            }
                            id={'specification'}
                            onChange={formik.setFieldValue}
                        />

Det jag vill lyfta fram är att id:t för redigeraren är specification.

För att skriva testet för det i Cypress, installerade jag paketet jag nämnde, https://github.com/ForeachOS/cypress-tinymce.

Efter att jag installerade paketet och importerade det i filen support/index.ts, kan jag inte bara anropa funktionen på följande sätt:

cy.setTinyMceContent('specification', 'This is the new content');

Jag måste lägga till följande kod för att göra den kompatibel med TypeScript:

declare namespace Cypress {
    interface Chainable<Subject = any> {
        setTinyMceContent(tinyMceId: string, content: any): void
    }
}

Sedan sätter jag värdet på TinyMCE-redigeringsfältet enligt följande i mitt Cypress-test:

cy.setTinyMceContent('specification', 'This is testing')

När jag kör testet får jag följande fel:

Cannot read properties of undefined (reading 'specification')

Vad är fel på min kod och hur kan jag fixa det?

Svar #1

Paketet cypress-tinymce verkar vara väldigt föråldrat. Det finns ingen editors-egenskap i den senaste versionen 6 av tinyMCE.

Följande är det bästa jag har hittills. Det finns ett par ställen där du behöver vänta på att redigeraren ska starta.

Den andra väntar på det aktuella textinnehållet, vilket inte är bra eftersom det är för specifikt. Jag har inte hittat ett bättre sätt att göra detta än.

Uppdaterad från @WaiYanHein kommentar

/// <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
  })
});

React-appen kontrollerar innehållet, du kan se att texten ändras till "Detta är det nya innehållet" och sedan återgår till "Lite text".

Jag tror att detta orsakas av att onChange()-händelsen utlöses, vilket renderar om komponenten och sätter tillbaka den till App:ens text.

På grund av det kan det vara bättre att styra React-appen genom app-åtgärder istället för att direkt använda tinyMCE API. Det beror på målen med ditt testande.

Svar #2

Cypress.Commands.add(
  "setTinyMceContent",
  (tinyMceId = "tiny-mce", content = "") => {
    cy.window().should("have.property", "tinymce"); // wait for tinyMCE
    cy.wait(500);
    cy.window().then((win) => {
      const editor = win.tinymce.EditorManager.get().find(
        (edtr) => edtr.id === tinyMceId
      );

      editor.setContent(content, { format: "text" });
      cy.wait(250);
      cy.wrap(editor.getContent({ format: "text" })).should("eq", content);
    });
  }
);

Detta är vad som fungerar för mig med v6