import { jsx, jsxs, Fragment } from 'solid-jsx/jsx-runtime';

/*@jsxRuntime automatic @jsxImportSource solid-jsx*/
const toc = [{
  "depth": 1,
  "value": "Testing Solid",
  "children": [{
    "depth": 2,
    "value": "Testing Setup",
    "children": [{
      "depth": 3,
      "value": "Setting up Jest",
      "children": [{
        "depth": 4,
        "value": "Jest with TypeScript (ts-jest)",
        "children": []
      }]
    }, {
      "depth": 3,
      "value": "Setting up uvu",
      "children": [{
        "depth": 4,
        "value": "Uvu with TypeScript (ts-uvu)",
        "children": []
      }, {
        "depth": 4,
        "value": "Uvu coverage Reports",
        "children": []
      }, {
        "depth": 4,
        "value": "Watch Mode",
        "children": []
      }]
    }]
  }, {
    "depth": 2,
    "value": "Testing Patterns and Best Practices",
    "children": [{
      "depth": 3,
      "value": "Testing Reactive State",
      "children": [{
        "depth": 4,
        "value": "Testing with Jest",
        "children": []
      }, {
        "depth": 4,
        "value": "Testing with uvu",
        "children": []
      }]
    }, {
      "depth": 3,
      "value": "Testing directives",
      "children": [{
        "depth": 4,
        "value": "Testing with Jest",
        "children": []
      }, {
        "depth": 4,
        "value": "Testing with uvu",
        "children": []
      }]
    }, {
      "depth": 3,
      "value": "Testing components",
      "children": [{
        "depth": 4,
        "value": "Testing with Jest",
        "children": []
      }, {
        "depth": 4,
        "value": "Testing with uvu",
        "children": []
      }]
    }]
  }]
}];
function _createMdxContent(props) {
  const _components = Object.assign({
    h1: "h1",
    a: "a",
    p: "p",
    h2: "h2",
    ul: "ul",
    li: "li",
    h3: "h3",
    code: "code",
    h4: "h4",
    pre: "pre",
    span: "span",
    blockquote: "blockquote"
  }, props.components);
  return jsxs(Fragment, {
    children: [jsxs(_components.h1, {
      id: "testing-solid",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-solid",
        children: "#"
      }), "Testing Solid"]
    }), "\n", jsx(_components.p, {
      children: "To use your Solid code in production, it needs to be tested. Since you don't want to test everything manually, you need automated tests. This guide describes how to set everything up and a few useful patterns for testing Solid code."
    }), "\n", jsxs(_components.h2, {
      id: "testing-setup",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-setup",
        children: "#"
      }), "Testing Setup"]
    }), "\n", jsx(_components.p, {
      children: "We offer support for two test runners:"
    }), "\n", jsxs(_components.ul, {
      children: ["\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "jest - very well established with many features"
        }), "\n"]
      }), "\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "uvu - only brings the bare necessities"
        }), "\n"]
      }), "\n"]
    }), "\n", jsxs(_components.p, {
      children: ["Both are based around ", jsx(_components.a, {
        href: "https://github.com/solidjs/solid-testing-library",
        children: "solid-testing-library"
      }), ", which integrates ", jsx(_components.a, {
        href: "https://testing-library.com/",
        children: "Testing Library"
      }), " into Solid. Testing Library mimics a light-weight browser and provides an API to interact with it from your tests."]
    }), "\n", jsx(_components.p, {
      children: "We maintain a starter template for Solid and Jest tests. We recommend you base your project on it, or alternatively install the starter template in a scratch project and copy the configuration from it into your own project."
    }), "\n", jsxs(_components.p, {
      children: ["The templates use the ", jsx(_components.a, {
        href: "https://github.com/Rich-Harris/degit",
        children: "degit"
      }), " utility for installation."]
    }), "\n", jsxs(_components.h3, {
      id: "setting-up-jest",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#setting-up-jest",
        children: "#"
      }), "Setting up Jest"]
    }), "\n", jsxs(_components.p, {
      children: ["The Jest integration is based around the ", jsx(_components.a, {
        href: "https://github.com/solidjs/solid-jest",
        children: "solid-jest/preset/browser"
      }), " Jest configuration preset which lets you use Solid as in the browser. This uses babel to transform the Solid code."]
    }), "\n", jsxs(_components.p, {
      children: ["It uses ", jsx(_components.a, {
        href: "https://github.com/testing-library/jest-dom",
        children: "jest-dom"
      }), " to extend ", jsx(_components.code, {
        children: "expect"
      }), " with a bunch of custom matchers that help you write tests."]
    }), "\n", jsxs(_components.h4, {
      id: "jest-with-typescript-ts-jest",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#jest-with-typescript-ts-jest",
        children: "#"
      }), "Jest with TypeScript (", jsx(_components.code, {
        children: "ts-jest"
      }), ")"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-bash",
        children: ["$ npx degit solidjs/templates/ts-jest my-solid-project\n$ ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "cd"
        }), " my-solid-project\n$ npm install ", jsx(_components.span, {
          className: "hljs-comment",
          children: "# or pnpm install or yarn install"
        }), "\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["Note that this template does not do typechecks during testing; you can use your IDE or a custom ", jsx(_components.code, {
        children: "tsc --noEmit"
      }), " script in ", jsx(_components.code, {
        children: "package.json"
      }), " to trigger such checks."]
    }), "\n", jsxs(_components.h3, {
      id: "setting-up-uvu",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#setting-up-uvu",
        children: "#"
      }), "Setting up uvu"]
    }), "\n", jsxs(_components.p, {
      children: ["We also maintain a starter template for ", jsx(_components.code, {
        children: "uvu"
      }), "."]
    }), "\n", jsxs(_components.p, {
      children: ["It includes ", jsx(_components.a, {
        href: "https://www.npmjs.com/package/solid-dom-testing",
        children: "solid-dom-testing"
      }), " to help you write assertions useful with Testing Library."]
    }), "\n", jsxs(_components.h4, {
      id: "uvu-with-typescript-ts-uvu",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#uvu-with-typescript-ts-uvu",
        children: "#"
      }), "Uvu with TypeScript (", jsx(_components.code, {
        children: "ts-uvu"
      }), ")"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-bash",
        children: ["$ npx degit solidjs/templates/ts-uvu my-solid-project\n$ ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "cd"
        }), " my-solid-project\n$ npm install ", jsx(_components.span, {
          className: "hljs-comment",
          children: "# or pnpm install or yarn install"
        }), "\n"]
      })
    }), "\n", jsxs(_components.h4, {
      id: "uvu-coverage-reports",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#uvu-coverage-reports",
        children: "#"
      }), "Uvu coverage Reports"]
    }), "\n", jsxs(_components.blockquote, {
      children: ["\n", jsxs(_components.p, {
        children: ["Unfortunately, due to a ", jsx(_components.a, {
          href: "https://github.com/babel/babel/issues/4289",
          children: "limitation of babel"
        }), ", we cannot get source maps output for transpiled JSX, which will result in components to show zero coverage. It will work for non-JSX code, though."]
      }), "\n"]
    }), "\n", jsx(_components.p, {
      children: "If you want to check code coverage of your tests, the favorite tool for uvu is c8. To install and set it up, run:"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-sh",
        children: ["> npm i --save-dev c8 ", jsx(_components.span, {
          className: "hljs-comment",
          children: "# or yarn add -D or pnpm"
        }), "\n> npm set-script ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"test:coverage\""
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"c8 uvu -r solid-register\""
        }), "\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["Now if you ", jsx(_components.code, {
        children: "npm run test:coverage"
      }), ", you'll see the test coverage."]
    }), "\n", jsxs(_components.p, {
      children: ["If you want nice HTML coverage reports, you can use ", jsx(_components.code, {
        children: "c8 -r html"
      }), " instead of ", jsx(_components.code, {
        children: "c8"
      }), " to enable the html reporter."]
    }), "\n", jsxs(_components.h4, {
      id: "watch-mode",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#watch-mode",
        children: "#"
      }), "Watch Mode"]
    }), "\n", jsxs(_components.p, {
      children: [jsx(_components.code, {
        children: "uvu"
      }), " does not have a watch mode out of the box, but you can use ", jsx(_components.code, {
        children: "chokidar-cli"
      }), " to do the same:"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-sh",
        children: ["> npm i --save-dev chokidar-cli ", jsx(_components.span, {
          className: "hljs-comment",
          children: "# or yarn add -D or pnpm"
        }), "\n> npm set-script ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"test:watch\""
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"chokidar src/**/*.ts src/**/*.tsx -c \\\"uvu -r solid-register\\\"\n# use .js/.jsx instead of .ts/.tsx\n"
        })]
      })
    }), "\n", jsxs(_components.p, {
      children: ["Now if you run ", jsx(_components.code, {
        children: "npm run test:watch"
      }), ", the tests will run every time you change a file."]
    }), "\n", jsxs(_components.h2, {
      id: "testing-patterns-and-best-practices",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-patterns-and-best-practices",
        children: "#"
      }), "Testing Patterns and Best Practices"]
    }), "\n", jsx(_components.p, {
      children: "Now that you have installed your testing tools, you should start to use them. In order to make this easier, Solid supports a few nice patterns."
    }), "\n", jsxs(_components.h3, {
      id: "testing-reactive-state",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-reactive-state",
        children: "#"
      }), "Testing Reactive State"]
    }), "\n", jsxs(_components.p, {
      children: ["You may want to keep parts of your state separate from the components for ease of maintenance or being able to support multiple views. In this case, the interface against which you are testing is the state itself. Keep in mind that out of a ", jsx(_components.a, {
        href: "https://www.solidjs.com/docs/latest/api#createroot",
        children: "reactive root"
      }), " your state is not tracked and updates won't trigger effects and memos."]
    }), "\n", jsxs(_components.p, {
      children: ["Also, since effects trigger asynchronously, it can help to wrap our assertions in a final effect. Alternatively, to observe a sequence of effects over multiple changes, it can help to return the necessary tools from ", jsx(_components.code, {
        children: "createRoot"
      }), " and execute them in an async test function (as ", jsx(_components.code, {
        children: "createRoot"
      }), " itself cannot take an ", jsx(_components.code, {
        children: "async"
      }), " function)."]
    }), "\n", jsxs(_components.p, {
      children: ["As an example, let's test ", jsx(_components.code, {
        children: "createLocalStorage"
      }), " from the ", jsx(_components.a, {
        href: "https://www.solidjs.com/examples/todos",
        children: "todo example"
      }), ":"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createEffect } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createStore, ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Store"
        }), ", ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "SetStoreFunction"
        }), " } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/store\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "export"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "function"
        }), " createLocalStore<T>(\n  ", jsx(_components.span, {
          className: "hljs-attr",
          children: "initState"
        }), ": T\n): [", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Store"
        }), "<T>, ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "SetStoreFunction"
        }), "<T>] {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [state, setState] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createStore"
        }), "(initState);\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "if"
        }), " (", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), ") ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setState"
        }), "(", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "parse"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), "));\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createEffect"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " (", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), " = ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "stringify"
        }), "(state)));\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " [state, setState];\n}\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["Instead of creating a TODO component, we can test this model in isolation; when we do that, we need to keep in mind that 1. reactive changes only work when they have a tracking context provided by ", jsx(_components.code, {
        children: "render"
      }), " or ", jsx(_components.code, {
        children: "createRoot"
      }), " and 2. are asynchronous, but we can use ", jsx(_components.code, {
        children: "createEffect"
      }), " to catch them. Using ", jsx(_components.code, {
        children: "createRoot"
      }), " has the advantage that we can trigger the disposal manually:"]
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-jest",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-jest",
        children: "#"
      }), "Testing with Jest"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createLocalStore } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"./main.tsx\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createRoot, createEffect } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "describe"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"createLocalStore\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "beforeEach"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "removeItem"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"todos\""
        }), ");\n  });\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " initialState = {\n    ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n    ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), ",\n  };\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it reads pre-existing state from localStorage\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), " {\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " savedState = { ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [], ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"saved\""
        }), " };\n      ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setItem"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"todos\""
        }), ", ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "stringify"
        }), "(savedState));\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [state] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createLocalStore"
        }), "(initialState);\n      ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(state).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toEqual"
        }), "(savedState);\n      ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n    }));\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it stores new state to localStorage\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), " {\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [state, setState] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createLocalStore"
        }), "(initialState);\n      ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setState"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"newTitle\""
        }), ", ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"updated\""
        }), ");\n      ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// to catch an effect, use an effect"
        }), "\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), "\n        ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createEffect"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "parse"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), " || ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), ")).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toEqual"
        }), "({\n            ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n            ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"updated\""
        }), ",\n          });\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n        })\n      );\n    }));\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it updates state multiple times\""
        }), ", ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "async"
        }), " () => {\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " { dispose, setState } = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), " {\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [state, setState] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createLocalStore"
        }), "(initialState);\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " { dispose, setState };\n    });\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setState"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"newTitle\""
        }), ", ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"first\""
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// wait a tick to resolve all effects"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "done"
          }), ") =>"]
        }), " ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "setTimeout"
        }), "(done, ", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), "));\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "parse"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), " || ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), ")).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toEqual"
        }), "({\n      ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n      ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"first\""
        }), ",\n    });\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setState"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"newTitle\""
        }), ", ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"second\""
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "done"
          }), ") =>"]
        }), " ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "setTimeout"
        }), "(done, ", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), "));\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "parse"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), " || ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), ")).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toEqual"
        }), "({\n      ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n      ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"first\""
        }), ",\n    });\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n  });\n});\n"]
      })
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-uvu",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-uvu",
        children: "#"
      }), "Testing with uvu"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createLocalStore } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"./main\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { suite } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"uvu\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " * ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "as"
        }), " assert ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"uvu/assert\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createEffect, createRoot } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " todoTest = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "suite"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"createLocalStore\""
        }), ");\n\ntodoTest.", jsx(_components.span, {
          className: "hljs-property",
          children: "before"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "each"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "removeItem"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"todos\""
        }), ");\n});\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " initialState = {\n  ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n  ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), ",\n};\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "todoTest"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it reads pre-existing state from localStorage\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " savedState = { ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [], ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"saved\""
        }), " };\n    ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setItem"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"todos\""
        }), ", ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "stringify"
        }), "(savedState));\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [state] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createLocalStore"
        }), "(initialState);\n    assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "equal"
        }), "(state, savedState);\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n  })\n);\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "todoTest"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it stores new state to localStorage\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [_, setState] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createLocalStore"
        }), "(initialState);\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setState"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"newTitle\""
        }), ", ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"updated\""
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// to catch an effect, we need an effect"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), "\n      ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createEffect"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n        assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "equal"
        }), "(", jsx(_components.span, {
          className: "hljs-title class_",
          children: "JSON"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "parse"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "localStorage"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "todos"
        }), " || ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"\""
        }), "), {\n          ", jsx(_components.span, {
          className: "hljs-attr",
          children: "todos"
        }), ": [],\n          ", jsx(_components.span, {
          className: "hljs-attr",
          children: "newTitle"
        }), ": ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"updated\""
        }), ",\n        });\n        ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n        ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n      })\n    );\n  })\n);\n\ntodoTest.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "run"
        }), "();\n"]
      })
    }), "\n", jsxs(_components.h3, {
      id: "testing-directives",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-directives",
        children: "#"
      }), "Testing directives"]
    }), "\n", jsxs(_components.p, {
      children: [jsx(_components.a, {
        href: "https://www.solidjs.com/docs/latest/api#use%3A___",
        children: "Directives"
      }), " allow using refs in a reusable way. They are basically functions that follow the pattern ", jsx(_components.code, {
        children: "(ref: HTMLElement, data: Accessor<any>) => void"
      }), ". In our ", jsx(_components.a, {
        href: "https://www.solidjs.com/tutorial/bindings_directives?solved",
        children: "directives tutorial"
      }), ", we define the ", jsx(_components.code, {
        children: "clickOutside"
      }), " directive that should call the callback wrapped in the accessor argument."]
    }), "\n", jsx(_components.p, {
      children: "We could now create a component and use the directive in there, but then we'd be testing the use of directives instead of directly testing the directive. It's simpler to test the surface of the directive by providing a mounted node and the accessor:"
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-jest-1",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-jest-1",
        children: "#"
      }), "Testing with Jest"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-comment",
          children: "// click-outside.test.ts"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " clickOutside ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click-outside\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createRoot } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { fireEvent } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-testing-library\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "describe"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"clickOutside\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ref = ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createElement"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"div\""
        }), ");\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "beforeAll"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "appendChild"
        }), "(ref);\n  });\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "afterAll"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "removeChild"
        }), "(ref);\n  });\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"will trigger on click outside\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(\n      ", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), "\n        ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), " {\n          ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "let"
        }), " clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "false"
        }), ";\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickOutside"
        }), "(ref, ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n            clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "true"
        }), ";\n          });\n          ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "addEventListener"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(clickedOutside).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toBeTruthy"
        }), "();\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n          });\n          fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ");\n        })\n    ));\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"will not trigger on click inside\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(\n      ", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), "\n        ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), " {\n          ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "let"
        }), " clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "false"
        }), ";\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickOutside"
        }), "(ref, ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n            clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "true"
        }), ";\n          });\n          ref.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "addEventListener"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(clickedOutside).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toBeFalsy"
        }), "();\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n            ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n          });\n          fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(ref);\n        })\n    ));\n});\n"]
      })
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-uvu-1",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-uvu-1",
        children: "#"
      }), "Testing with uvu"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-comment",
          children: "// click-outside.test.ts"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " clickOutside ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click-outside.tsx\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createRoot } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { fireEvent } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-testing-library\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " clickTest = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "suite"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"clickOutside\""
        }), ");\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ref = ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createElement"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"div\""
        }), ");\n\nclickTest.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "before"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "appendChild"
        }), "(ref);\n});\n\nclickTest.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "after"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "removeChild"
        }), "(ref);\n});\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickTest"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"will trigger on click outside\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(\n    ", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), "\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), " {\n        ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "let"
        }), " clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "false"
        }), ";\n        ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickOutside"
        }), "(ref, ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n          clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "true"
        }), ";\n        });\n        ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "addEventListener"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n          assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "ok"
        }), "(clickedOutside);\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n        });\n        fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-property",
          children: "body"
        }), ");\n      })\n  )\n);\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickTest"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"will not trigger on click inside\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), "\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createRoot"
        }), "(\n    ", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "dispose"
          }), ") =>"]
        }), "\n      ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), "<", jsx(_components.span, {
          className: "hljs-built_in",
          children: "void"
        }), ">(", jsxs(_components.span, {
          className: "hljs-function",
          children: ["(", jsx(_components.span, {
            className: "hljs-params",
            children: "resolve"
          }), ") =>"]
        }), " {\n        ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "let"
        }), " clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "false"
        }), ";\n        ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "clickOutside"
        }), "(ref, ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n          clickedOutside = ", jsx(_components.span, {
          className: "hljs-literal",
          children: "true"
        }), ";\n        });\n        ref.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "addEventListener"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n          assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "is"
        }), "(clickedOutside, ", jsx(_components.span, {
          className: "hljs-literal",
          children: "false"
        }), ");\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "dispose"
        }), "();\n          ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n        });\n        fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(ref);\n      })\n  )\n);\n\nclickTest.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "run"
        }), "();\n"]
      })
    }), "\n", jsxs(_components.h3, {
      id: "testing-components",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-components",
        children: "#"
      }), "Testing components"]
    }), "\n", jsx(_components.p, {
      children: "Let's take a simple click-counter component that we want to test:"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-comment",
          children: "// main.tsx"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createSignal, ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Component"
        }), " } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "export"
        }), " ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Counter"
        }), ": ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Component"
        }), " = ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [count, setCount] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), ");\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " (\n    ", jsxs(_components.span, {
          className: "xml",
          children: [jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "role"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"button\""
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "onClick"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "{()"
            }), " =>"]
          }), " setCount((c) => c + 1)}>\n      Count: {count()}\n    ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), ">"]
          })]
        }), "\n  );\n};\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["Here we use ", jsx(_components.code, {
        children: "solid-testing-library"
      }), ". It's most important helpers are ", jsx(_components.code, {
        children: "render"
      }), " to render a component to the DOM in a managed way, ", jsx(_components.code, {
        children: "fireEvent"
      }), " to dispatch events in a way that resembles actual user events and ", jsx(_components.code, {
        children: "screen"
      }), " to provide global selectors. We also use helpful assertions added to ", jsx(_components.code, {
        children: "expect"
      }), " provided by ", jsx(_components.code, {
        children: "@testing-library/jest-dom"
      }), "."]
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-jest-2",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-jest-2",
        children: "#"
      }), "Testing with Jest"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-comment",
          children: "// main.test.tsx"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Counter"
        }), " } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"./main\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { cleanup, fireEvent, render, screen } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-testing-library\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "describe"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Counter\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "afterEach"
        }), "(cleanup);\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it starts with zero\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "Counter"
            }), " />"]
          })
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " button = screen.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getByRole"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"button\""
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(button).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toBeInTheDocument"
        }), "();\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(button).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toHaveTextContent"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 0\""
        }), ");\n  });\n\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "test"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it increases its value on click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "async"
        }), " () => {\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "Counter"
            }), " />"]
          })
        }), ");\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " button = screen.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getByRole"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"button\""
        }), ");\n    fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(button);\n    ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// the event loop takes one Promise to resolve to be finished"
        }), "\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(button).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toHaveTextContent"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 1\""
        }), ");\n    fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(button);\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "expect"
        }), "(button).", jsx(_components.span, {
          className: "hljs-title function_",
          children: "toHaveTextContent"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 2\""
        }), ");\n  });\n});\n"]
      })
    }), "\n", jsxs(_components.h4, {
      id: "testing-with-uvu-2",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#testing-with-uvu-2",
        children: "#"
      }), "Testing with uvu"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-ts",
        children: [jsx(_components.span, {
          className: "hljs-comment",
          children: "// main.test.tsx"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { suite } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"uvu\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " * ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "as"
        }), " assert ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"uvu/assert\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Counter"
        }), " } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"main\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { fireEvent, render, screen } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-testing-library\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { isInDocument, hasTextContent } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-dom-testing\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " testCounter = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "suite"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Counter\""
        }), ");\n\ntestCounter.", jsx(_components.span, {
          className: "hljs-property",
          children: "after"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "each"
        }), "(cleanup);\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "testCounter"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it starts with zero\""
        }), ", ", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " { getByRole } = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "Counter"
            }), " />"]
          })
        }), ");\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " button = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getByRole"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"button\""
        }), ");\n  assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "ok"
        }), "(", jsx(_components.span, {
          className: "hljs-title function_",
          children: "isInDocument"
        }), "(button), ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"button not in dom\""
        }), ");\n  assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "ok"
        }), "(", jsx(_components.span, {
          className: "hljs-title function_",
          children: "hasTextContent"
        }), "(button, ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 0\""
        }), "), ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"wrong text content\""
        }), ");\n});\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "testCounter"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"it increases its value on click\""
        }), ", ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "async"
        }), " () => {\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "Counter"
            }), " />"]
          })
        }), ");\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " button = screen.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getByRole"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"button\""
        }), ");\n  fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(button);\n  ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// the event loop takes one Promise to resolve to be finished"
        }), "\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n  assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "ok"
        }), "(\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "hasTextContent"
        }), "(button, ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 1\""
        }), "),\n    ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"not count 1 after first click\""
        }), "\n  );\n  fireEvent.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "click"
        }), "(button);\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Promise"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "resolve"
        }), "();\n  assert.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "ok"
        }), "(\n    ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "hasTextContent"
        }), "(button, ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"Count: 2\""
        }), "),\n    ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"not count 2 after first click\""
        }), "\n  );\n});\n\ntestCounter.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "run"
        }), "();\n"]
      })
    })]
  });
}
function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? jsx(MDXLayout, Object.assign({}, props, {
    children: jsx(_createMdxContent, props)
  })) : _createMdxContent(props);
}

export { MDXContent as default, toc };
//# sourceMappingURL=testing-e093a769.js.map
