From 737aaa9cde2d4a2d6d64b83256aa5d9d1b5ce720 Mon Sep 17 00:00:00 2001 From: Julian Krispel-Samsel Date: Mon, 26 Apr 2021 14:47:12 +0100 Subject: [PATCH] Fix iframe crash (#4219) * fixes #4170 * add smoke test for iframe example * add changeset * update changeset wording --- .changeset/thick-apricots-fly.md | 5 +++ cypress/integration/iframe.ts | 31 +++++++++++++++++++ .../slate-react/src/plugin/react-editor.ts | 4 +++ 3 files changed, 40 insertions(+) create mode 100644 .changeset/thick-apricots-fly.md create mode 100644 cypress/integration/iframe.ts diff --git a/.changeset/thick-apricots-fly.md b/.changeset/thick-apricots-fly.md new file mode 100644 index 000000000..b13ab1a7b --- /dev/null +++ b/.changeset/thick-apricots-fly.md @@ -0,0 +1,5 @@ +--- +'slate-react': patch +--- + +Fixes error that occurs when Editor is rendered inside iframe diff --git a/cypress/integration/iframe.ts b/cypress/integration/iframe.ts new file mode 100644 index 000000000..ddeddc9ac --- /dev/null +++ b/cypress/integration/iframe.ts @@ -0,0 +1,31 @@ +// Taken from https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/ +const getIframeDocument = () => { + return cy + .get('iframe') + .its('0.contentDocument') + .should('exist') +} + +const getIframeBody = () => { + return ( + getIframeDocument() + .its('body') + // automatically retries until body is loaded + .should('not.be.undefined') + .then(cy.wrap) + ) +} + +describe('iframe editor', () => { + beforeEach(() => { + cy.visit('examples/iframe') + }) + + it('should be editable', () => { + getIframeBody() + .findByRole('textbox') + .type('{movetostart}') + .type('Hello World') + .should('contain.text', 'Hello World') + }) +}) diff --git a/packages/slate-react/src/plugin/react-editor.ts b/packages/slate-react/src/plugin/react-editor.ts index e766b397a..b824b0c2e 100644 --- a/packages/slate-react/src/plugin/react-editor.ts +++ b/packages/slate-react/src/plugin/react-editor.ts @@ -106,6 +106,10 @@ export const ReactEditor = { const el = ReactEditor.toDOMNode(editor, editor) const root = el.getRootNode() + // The below exception will always be thrown for iframes because the document inside an iframe + // does not inherit it's prototype from the parent document, therefore we return early + if (el.ownerDocument !== document) return el.ownerDocument + if (!(root instanceof Document || root instanceof ShadowRoot)) throw new Error( `Unable to find DocumentOrShadowRoot for editor element: ${el}`