test: add tests for components/editor (#15938)
* test: add VariableNode test suite * test: add ToolbarPlugin test suite * test: add AutoLinkPlugin test suite * test: add AddVariablesDropdown test suite * test: add Editor test suite * chore: Remove unnecessary comments in ToolbarPlugin.test.tsx --------- Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
This commit is contained in:
co-authored by
Amit Sharma
parent
24e5226e3e
commit
63c7e4b55a
@@ -0,0 +1,79 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
|
||||
import type { TextEditorProps } from "./Editor";
|
||||
import { Editor } from "./Editor";
|
||||
|
||||
describe("Editor", () => {
|
||||
const defaultProps: TextEditorProps = {
|
||||
getText: vi.fn(),
|
||||
setText: vi.fn(),
|
||||
variables: ["name", "email"],
|
||||
height: "200px",
|
||||
placeholder: "Start typing...",
|
||||
};
|
||||
|
||||
it("renders editor with default props", () => {
|
||||
render(<Editor {...defaultProps} />);
|
||||
expect(screen.getByRole("textbox")).toBeInTheDocument();
|
||||
expect(screen.getByText("Start typing...")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders toolbar", () => {
|
||||
render(<Editor {...defaultProps} />);
|
||||
expect(screen.getByText("Normal")).toBeInTheDocument();
|
||||
expect(screen.getByText("add_variable")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("respects editable prop", () => {
|
||||
render(<Editor {...defaultProps} editable={false} />);
|
||||
const editor = screen.getByTestId("editor-input");
|
||||
// eslint-disable-next-line playwright/missing-playwright-await
|
||||
expect(editor).toHaveAttribute("contenteditable", "false");
|
||||
});
|
||||
|
||||
it("excludes toolbar items", () => {
|
||||
render(<Editor {...defaultProps} excludedToolbarItems={["bold", "italic"]} />);
|
||||
expect(screen.queryByTitle("Bold")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTitle("Italic")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders variables plugin when variables are provided", () => {
|
||||
render(<Editor {...defaultProps} />);
|
||||
expect(screen.getByText("add_variable")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not render variables plugin when variables are not provided", () => {
|
||||
render(<Editor {...defaultProps} variables={undefined} />);
|
||||
expect(screen.queryByText("add_variable")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("disables lists when disableLists is true", () => {
|
||||
render(<Editor {...defaultProps} disableLists={true} />);
|
||||
expect(screen.queryByTitle("Bullet List")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTitle("Numbered List")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("calls getText when text is entered", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<Editor {...defaultProps} />);
|
||||
const editor = screen.getByRole("textbox");
|
||||
await user.type(editor, "Hello, world!");
|
||||
expect(defaultProps.getText).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applies custom height", () => {
|
||||
render(<Editor {...defaultProps} height="300px" />);
|
||||
const editorInner = screen.getByRole("textbox").parentElement;
|
||||
expect(editorInner).toHaveStyle({ height: "300px" });
|
||||
});
|
||||
|
||||
it("handles first render and update template", () => {
|
||||
const setFirstRender = vi.fn();
|
||||
render(
|
||||
<Editor {...defaultProps} updateTemplate={true} firstRender={true} setFirstRender={setFirstRender} />
|
||||
);
|
||||
expect(setFirstRender).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -88,6 +88,7 @@ export const Editor = (props: TextEditorProps) => {
|
||||
<RichTextPlugin
|
||||
contentEditable={
|
||||
<ContentEditable
|
||||
data-testid="editor-input"
|
||||
readOnly={!editable}
|
||||
style={{ height: props.height }}
|
||||
className="editor-input"
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { createEditor, TextNode, type LexicalEditor } from "lexical";
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
|
||||
import { $createVariableNode, $isVariableNode, VariableNode } from "./VariableNode";
|
||||
|
||||
let editor: LexicalEditor;
|
||||
|
||||
beforeEach(() => {
|
||||
editor = createEditor({
|
||||
nodes: [VariableNode],
|
||||
});
|
||||
});
|
||||
|
||||
describe("VariableNode", () => {
|
||||
it("should create a VariableNode with given text", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
expect(node.getTextContent()).toBe("test");
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a VariableNode with default text", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode();
|
||||
expect(node.getTextContent()).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
it("should clone a VariableNode", () => {
|
||||
editor.update(() => {
|
||||
const original = $createVariableNode("test");
|
||||
const clone = VariableNode.clone(original);
|
||||
expect(clone.getTextContent()).toBe("test");
|
||||
expect(clone.__key).not.toBe(original.__key);
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a DOM element with correct attributes", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
const dom = node.createDOM(editor._config);
|
||||
expect(dom.className).toBe("bg-info");
|
||||
expect(dom.getAttribute("data-lexical-variable")).toBe("true");
|
||||
});
|
||||
});
|
||||
|
||||
it("should export JSON correctly", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
const json = node.exportJSON();
|
||||
expect(json).toEqual({
|
||||
...node.exportJSON(),
|
||||
type: "variable",
|
||||
version: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should return true for isTextEntity", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
expect(node.isTextEntity()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false for canInsertTextBefore and canInsertTextAfter", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
expect(node.canInsertTextBefore()).toBe(false);
|
||||
expect(node.canInsertTextAfter()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it("should identify a VariableNode correctly", () => {
|
||||
editor.update(() => {
|
||||
const node = $createVariableNode("test");
|
||||
expect($isVariableNode(node)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not identify a non-VariableNode", () => {
|
||||
editor.update(() => {
|
||||
const node = new TextNode("test");
|
||||
expect($isVariableNode(node)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
||||
import { vi, describe, it, expect } from "vitest";
|
||||
|
||||
import { AddVariablesDropdown } from "./AddVariablesDropdown";
|
||||
|
||||
vi.mock("@calcom/lib/hooks/useLocale", () => ({
|
||||
useLocale: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock the Dropdown component
|
||||
vi.mock("../../form/dropdown", () => ({
|
||||
Dropdown: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
DropdownMenuTrigger: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
DropdownMenuContent: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
DropdownMenuItem: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
}));
|
||||
|
||||
describe("AddVariablesDropdown", () => {
|
||||
const mockAddVariable = vi.fn();
|
||||
const variables = ["var1", "var2", "var3"];
|
||||
|
||||
it("renders correctly", () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} />);
|
||||
expect(screen.getByText("add_variable")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders text editor version correctly", () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} isTextEditor />);
|
||||
expect(screen.getByText("add_variable")).toBeInTheDocument();
|
||||
expect(screen.getByText("+")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens dropdown on click", async () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} />);
|
||||
fireEvent.click(screen.getByText("add_variable"));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("add_dynamic_variables".toLocaleUpperCase())).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("renders all variables", async () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} />);
|
||||
fireEvent.click(screen.getByText("add_variable"));
|
||||
await waitFor(() => {
|
||||
for (const variable of variables) {
|
||||
expect(
|
||||
screen.getByText((content) => content.includes(`{${variable}_variable}`.toUpperCase()))
|
||||
).toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("calls addVariable when a variable is clicked", async () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} />);
|
||||
fireEvent.click(screen.getByText("add_variable"));
|
||||
await waitFor(() => {
|
||||
fireEvent.click(screen.getByText((content) => content.includes("{VAR1_VARIABLE}")));
|
||||
});
|
||||
expect(mockAddVariable).toHaveBeenCalledWith("var1_variable");
|
||||
});
|
||||
|
||||
it("renders variable info for each variable", async () => {
|
||||
render(<AddVariablesDropdown addVariable={mockAddVariable} variables={variables} />);
|
||||
fireEvent.click(screen.getByText("add_variable"));
|
||||
await waitFor(() => {
|
||||
for (const variable of variables) {
|
||||
expect(screen.getByText(`${variable}_info`)).toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import { LexicalComposer } from "@lexical/react/LexicalComposer";
|
||||
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
||||
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
|
||||
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
import PlaygroundAutoLinkPlugin from "./AutoLinkPlugin";
|
||||
|
||||
const mockAutoLinkPlugin = vi.fn(() => null);
|
||||
|
||||
vi.mock("@lexical/react/LexicalAutoLinkPlugin", () => ({
|
||||
// @ts-expect-error - it needs props, somehow it not detect it.
|
||||
AutoLinkPlugin: (props: any) => mockAutoLinkPlugin(props),
|
||||
}));
|
||||
|
||||
function setup() {
|
||||
const initialConfig = {
|
||||
namespace: "test-editor",
|
||||
onError: (error: Error) => console.error(error),
|
||||
};
|
||||
|
||||
return render(
|
||||
<LexicalComposer initialConfig={initialConfig}>
|
||||
<RichTextPlugin
|
||||
contentEditable={<ContentEditable />}
|
||||
placeholder={<div>Enter some text...</div>}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<PlaygroundAutoLinkPlugin />
|
||||
</LexicalComposer>
|
||||
);
|
||||
}
|
||||
|
||||
describe("PlaygroundAutoLinkPlugin", () => {
|
||||
beforeEach(() => {
|
||||
mockAutoLinkPlugin.mockClear();
|
||||
});
|
||||
|
||||
it("renders without crashing", () => {
|
||||
setup();
|
||||
expect(screen.getByText("Enter some text...")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("passes correct matchers to AutoLinkPlugin", () => {
|
||||
setup();
|
||||
expect(mockAutoLinkPlugin).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
matchers: expect.arrayContaining([expect.any(Function), expect.any(Function)]),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("correctly matches URLs", () => {
|
||||
setup();
|
||||
// @ts-expect-error - it's definitely not undefined
|
||||
const matchers = mockAutoLinkPlugin.mock.calls[0][0].matchers;
|
||||
const urlMatcher = matchers[0];
|
||||
|
||||
const validUrls = ["https://www.example.com", "http://example.com", "www.example.com"];
|
||||
|
||||
validUrls.forEach((url) => {
|
||||
const result = urlMatcher(url);
|
||||
expect(result).toEqual({
|
||||
index: 0,
|
||||
length: url.length,
|
||||
text: url,
|
||||
url: url,
|
||||
});
|
||||
});
|
||||
|
||||
expect(urlMatcher("not a url")).toBeNull();
|
||||
});
|
||||
|
||||
it("correctly matches email addresses", () => {
|
||||
setup();
|
||||
// @ts-expect-error - it's definitely not undefined
|
||||
const matchers = mockAutoLinkPlugin.mock.calls[0][0].matchers;
|
||||
const emailMatcher = matchers[1];
|
||||
|
||||
const validEmails = ["test@example.com", "test.name@example.co.uk", "test+alias@example.com"];
|
||||
|
||||
validEmails.forEach((email) => {
|
||||
const result = emailMatcher(email);
|
||||
expect(result).toEqual({
|
||||
index: 0,
|
||||
length: email.length,
|
||||
text: email,
|
||||
url: `mailto:${email}`,
|
||||
});
|
||||
});
|
||||
|
||||
expect(emailMatcher("not an email")).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,267 @@
|
||||
import { LexicalComposer } from "@lexical/react/LexicalComposer";
|
||||
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
||||
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
|
||||
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
|
||||
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
|
||||
import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
import ToolbarPlugin from "./ToolbarPlugin";
|
||||
|
||||
// Mocks
|
||||
vi.mock("../../..", () => ({
|
||||
Icon: ({ name }: { name: string }) => <span data-testid={`icon-${name}`}>{name}</span>,
|
||||
}));
|
||||
|
||||
vi.mock("../../button", () => ({
|
||||
Button: ({ children, onClick, StartIcon }: any) => (
|
||||
<button onClick={onClick} data-testid={`button-${StartIcon || "default"}`}>
|
||||
{StartIcon && <span>{StartIcon}</span>}
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("../../form/dropdown", () => ({
|
||||
Dropdown: ({ children }: any) => <div data-testid="dropdown">{children}</div>,
|
||||
DropdownMenuTrigger: ({ children }: any) => <div data-testid="dropdown-trigger">{children}</div>,
|
||||
DropdownMenuContent: ({ children }: any) => <div data-testid="dropdown-content">{children}</div>,
|
||||
DropdownMenuItem: ({ children }: any) => <div data-testid="dropdown-item">{children}</div>,
|
||||
}));
|
||||
|
||||
vi.mock("./AddVariablesDropdown", () => ({
|
||||
AddVariablesDropdown: () => <div data-testid="add-variables-dropdown">AddVariablesDropdown</div>,
|
||||
}));
|
||||
|
||||
const initialConfig = {
|
||||
namespace: "MyEditor",
|
||||
theme: {},
|
||||
onError: (error: Error) => console.error(error),
|
||||
};
|
||||
|
||||
const TestWrapper = ({ children }: { children: string | JSX.Element }) => (
|
||||
<LexicalComposer initialConfig={initialConfig}>
|
||||
<RichTextPlugin
|
||||
contentEditable={<ContentEditable />}
|
||||
placeholder={<div>Enter some text...</div>}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<HistoryPlugin />
|
||||
{children}
|
||||
</LexicalComposer>
|
||||
);
|
||||
|
||||
describe("ToolbarPlugin", () => {
|
||||
const defaultProps = {
|
||||
editable: true,
|
||||
getText: vi.fn(() => ""),
|
||||
setText: vi.fn(),
|
||||
firstRender: true,
|
||||
setFirstRender: vi.fn(),
|
||||
updateTemplate: false,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("renders correctly with default props", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("dropdown")).toBeDefined();
|
||||
expect(screen.getByTestId("button-bold")).toBeDefined();
|
||||
expect(screen.getByTestId("button-italic")).toBeDefined();
|
||||
expect(screen.getByTestId("button-link")).toBeDefined();
|
||||
});
|
||||
|
||||
it("does not render when editable is false", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} editable={false} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.queryByTestId("dropdown")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders variables dropdown when variables prop is provided", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} variables={["var1", "var2"]} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("add-variables-dropdown")).toBeDefined();
|
||||
});
|
||||
|
||||
it("excludes toolbar items when specified", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} excludedToolbarItems={["bold", "italic"]} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
expect(screen.queryByTestId("button-bold")).toBeNull();
|
||||
expect(screen.queryByTestId("button-italic")).toBeNull();
|
||||
expect(screen.getByTestId("button-link")).toBeDefined();
|
||||
});
|
||||
|
||||
it("changes block type when dropdown item is clicked", async () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByTestId("dropdown-trigger"));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId("dropdown-content")).toBeDefined();
|
||||
});
|
||||
|
||||
const h1Button = screen.getByText("Large Heading");
|
||||
fireEvent.click(h1Button);
|
||||
});
|
||||
|
||||
it("toggles bold formatting when bold button is clicked", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const boldButton = screen.getByTestId("button-bold");
|
||||
fireEvent.click(boldButton);
|
||||
});
|
||||
|
||||
it("toggles italic formatting when italic button is clicked", () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const italicButton = screen.getByTestId("button-italic");
|
||||
fireEvent.click(italicButton);
|
||||
});
|
||||
|
||||
it("toggles link when link button is clicked", async () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const linkButton = screen.getByTestId("button-link");
|
||||
fireEvent.click(linkButton);
|
||||
});
|
||||
|
||||
// Additional tests
|
||||
it("calls setText when editor content changes", async () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const editableContent = screen.getByRole("textbox");
|
||||
await userEvent.type(editableContent, "Hello, World!");
|
||||
|
||||
expect(defaultProps.setText).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("updates editor content when updateTemplate prop changes", async () => {
|
||||
const getText = vi.fn(() => "<p>Initial content</p>");
|
||||
const setText = vi.fn();
|
||||
const setFirstRender = vi.fn();
|
||||
|
||||
const { rerender } = render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin
|
||||
{...defaultProps}
|
||||
getText={getText}
|
||||
setText={setText}
|
||||
setFirstRender={setFirstRender}
|
||||
firstRender={true}
|
||||
updateTemplate={false}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
// Wait for initial render
|
||||
await waitFor(() => {
|
||||
expect(setFirstRender).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
// Update getText mock and trigger update
|
||||
getText.mockReturnValue("<p>Updated content</p>");
|
||||
|
||||
await act(async () => {
|
||||
rerender(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin
|
||||
{...defaultProps}
|
||||
getText={getText}
|
||||
setText={setText}
|
||||
setFirstRender={setFirstRender}
|
||||
firstRender={false}
|
||||
updateTemplate={true}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
// Wait for content update
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(setText).toHaveBeenCalledWith(expect.stringContaining("Updated content"));
|
||||
},
|
||||
{ timeout: 5000 }
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes editor with provided text", async () => {
|
||||
const getText = vi.fn(() => "<p>Initial content</p>");
|
||||
const setText = vi.fn();
|
||||
const setFirstRender = vi.fn();
|
||||
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin
|
||||
{...defaultProps}
|
||||
getText={getText}
|
||||
setText={setText}
|
||||
setFirstRender={setFirstRender}
|
||||
firstRender={true}
|
||||
/>
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(setFirstRender).toHaveBeenCalledWith(false);
|
||||
expect(setText).toHaveBeenCalledWith(expect.stringContaining("Initial content"));
|
||||
},
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
});
|
||||
|
||||
it("calls setText after content update", async () => {
|
||||
const setText = vi.fn();
|
||||
await act(async () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<ToolbarPlugin {...defaultProps} setText={setText} getText={() => "<p>Test content</p>"} />
|
||||
</TestWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setText).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user