{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "playwright-docs",
  "title": "Playwright Testing",
  "description": "Learn how to write Playwright tests that integrate with Plate.",
  "files": [
    {
      "path": "../../content/docs/(guides)/playwright.mdx",
      "content": "---\ntitle: Playwright Testing\ndescription: Learn how to write Playwright tests that integrate with Plate.\n---\n\n[Playwright](https://playwright.dev/) enables end-to-end testing in headless browsers. This guide covers integrating Playwright with Plate using `@platejs/playwright`.\n\n## Setup\n\n<Steps>\n\n### Install Dependencies\n\nFollow [Playwright's guide](https://playwright.dev/docs/intro) to install Playwright in your app and ensure that you can write basic end-to-end tests.\n\n```bash\nnpm install @platejs/playwright playwright\n```\n\n### Add PlaywrightPlugin\n\nIn order for your Playwright tests to access and interact with the editor, you'll need to add `PlaywrightPlugin` to your editor:\n\n```tsx\nconst editor = createPlateEditor({\n  plugins: [\n    // other plugins...\n    PlaywrightPlugin.configure({ enabled: process.env.NODE_ENV !== 'production' }),\n  ]\n})\n```\n\nThis exposes various utilities on `window.platePlaywrightAdapter`.\n\n### Get Editor Handle\n\n<Callout type=\"info\" title=\"What is an editor handle?\">\n  Most Playwright test code runs in a non-browser environment. Interacting with a Plate editor requires running JavaScript inside the browser context using Playwright's `evaluate` and `evaluateHandle` [APIs](https://playwright.dev/docs/evaluating).\n\n  A [handle](https://playwright.dev/docs/handles) references a JavaScript object within the browser. The editor handle refers to the `editor` instance of your Plate editor (`JSHandle<PlateEditor>`).\n</Callout>\n\nIn your Playwright test, get the editor handle before interacting with Plate:\n\n```ts\nconst editorHandle = await getEditorHandle(page);\n```\n\nFor multiple editors, specify the editable element:\n\n```ts\nconst editable = getEditable(page.getByTestId('my-editor-container'));\nconst editorHandle = await getEditorHandle(page, editable);\n```\n\nThe locator must match exactly one `[data-slate-editor]` element.\n\n### Start Writing Tests\n\nWith the `editorHandle`, you can now write Playwright tests for your editor.\n\n</Steps>\n\n## Examples\n\n### Get a node handle by its path\n\nUse `getNodeByPath` to get a handle referencing the node at a specific path. To make assertions about the value of the node, convert it to JSON using `.jsonValue()`.\n\n```ts\nconst nodeHandle = await getNodeByPath(page, editorHandle, [0]);\n\nexpect(await nodeHandle.jsonValue()).toBe({\n  type: 'p',\n  children: [{ text: 'My paragraph' }],\n});\n```\n\n### Get the type of a node\n\n```ts\nconst firstNodeType = await getTypeAtPath(page, editorHandle, [0]);\nexpect(firstNodeType).toBe('h1');\n```\n\n### Get the DOM node for a node\n\nOften in Playwright, you'll want to reference a specific DOM element in order to make assertions about its state or perform operations involving it.\n\n`getDOMNodeByPath` returns an [ElementHandle](https://playwright.dev/docs/api/class-elementhandle) for the DOM node corresponding to the Plate node at a given path.\n\n```ts\nconst firstNodeEl = await getDOMNodeByPath(page, elementHandle, [0]);\nawait firstNodeEl.hover();\n```\n\n### Click a node\n\n```ts\nawait clickAtPath(page, elementHandle, [0]);\n```\n\n### Get the selection\n\n```ts\nconst selection = await getSelection(page, editorHandle);\n\nexpect(selection).toBe({\n  anchor: { path: [0, 0], offset: 0 },\n  focus: { path: [0, 0], offset: 7 },\n});\n```\n\n### Select a point or range\n\nIn order to type at a specific point in the editor, you'll need to select that point using `setSelection`.\n\nIf you select a single point (consisting of a `path` and an `offset`), the cursor will be placed at that point. If you select a range (consisting of an `anchor` and a `focus`), that range will be selected. If you select a path, the entire node at that path will be selected.\n\nMake sure you focus the editor before setting the selection. Focusing the editor using `editable.focus()` may not work correctly in WebKit, so the best way of doing this is with `clickAtPath`.\n\n```ts\n// Click the first paragraph to focus the editor \nawait clickAtPath(page, editorHandle, [0]);\n\nawait setSelection(page, editorHandle, {\n  path: [0, 0],\n  offset: 2,\n});\n\nawait page.keyboard.type('Hello world!');\n```\n\n## Imported queries and transforms\n\nYou may want to import a query or a transform such as `getBlockAbove` or `insertNodes` into your Playwright test and use it.\n\nUnfortunately, this is not possible. You can only interact directly with the `editor` instance inside the browser context (using `evaluate` or `evaluateHandle`), and it isn't possible to pass imported functions from Playwright's scope into the browser. This is because neither the `editor` object nor JavaScript functions can be adequately serialized.\n\nThe best workaround is to interact with the editor in the same way that a user would, without using any imported queries or transforms. This will make your Playwright tests more likely to catch bugs in your application.\n\nIf this isn't practical, you can instead call a method on the `editor` object inside an `evaluate` or `evaluateHandle`. (Use `evaluateHandle` if you need to return a reference to a DOM node or a JavaScript object from the browser. Use `evaluate` if you need to return a serialized copy of a JavaScript object, or if you don't need to return any value.)\n\nNote that while these queries and transforms can't be directly used in Playwright tests, they are available when working with the editor instance in your application code. For more information on how to use these methods in your application, refer to the [Editor Methods](/docs/editor-methods) documentation.\n\nSee [Playwright's docs](https://playwright.dev/docs/evaluating) for more information about `evaluate` and `evaluateHandle`.\n\n```ts\nawait editorHandle.evaluate((editor) => {\n  editor.tf.insertNodes(/* ... */);\n});\n```\n\nSee [Playwright's docs](https://playwright.dev/docs/evaluating) for more about `evaluate` and `evaluateHandle`.\n\n## API\n\n### `getEditorHandle`\n\nGets a handle to the Plate editor instance.\n\n<API name=\"getEditorHandle\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editable\" type=\"Locator\" optional>\n    Locator for editable element. Defaults to first [data-slate-editor].\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"EditorHandle\">\n  Handle to Plate editor instance.\n</APIReturns>\n</API>\n\n### `getNodeByPath`\n\nRetrieves a node at the specified path.\n\n<API name=\"getNodeByPath\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n  <APIItem name=\"path\" type=\"Path\">\n    Path to node.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"JSHandle<TNode>\">\n  Handle to node at path.\n</APIReturns>\n</API>\n\n### `getDOMNodeByPath`\n\nGets the DOM node for a Plate node at the given path.\n\n<API name=\"getDOMNodeByPath\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n  <APIItem name=\"path\" type=\"Path\">\n    Path to node.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"ElementHandle\">\n  ElementHandle for corresponding DOM node.\n</APIReturns>\n</API>\n\n### `clickAtPath`\n\nSimulates a click on the node at the specified path.\n\n<API name=\"clickAtPath\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n  <APIItem name=\"path\" type=\"Path\">\n    Path to node to click.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `getSelection`\n\nRetrieves the current editor selection.\n\n<API name=\"getSelection\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"Selection\">\n  Current editor selection.\n</APIReturns>\n</API>\n\n### `setSelection`\n\nSets the editor selection to the specified range.\n\n<API name=\"setSelection\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n  <APIItem name=\"at\" type=\"Location\">\n    Location to set selection.\n  </APIItem>\n</APIParameters>\n</API>\n\n### `getTypeAtPath`\n\nGets the type of the node at the specified path.\n\n<API name=\"getTypeAtPath\">\n<APIParameters>\n  <APIItem name=\"page\" type=\"Page\">\n    Playwright page object.\n  </APIItem>\n  <APIItem name=\"editorHandle\" type=\"EditorHandle\">\n    Handle to editor instance.\n  </APIItem>\n  <APIItem name=\"path\" type=\"Path\">\n    Path to node.\n  </APIItem>\n</APIParameters>\n\n<APIReturns type=\"string\">\n  Type of node at path.\n</APIReturns>\n</API>\n",
      "type": "registry:file",
      "target": "content/docs/plate/(guides)/playwright.mdx"
    }
  ],
  "type": "registry:file"
}