{"id":"flipbook-labs/react-testing-library-luau","name":"react-testing-library-luau","scope":"flipbook-labs","platform":"roblox","description":"Idiomatic-Luau testing library for React components on Roblox","version":"0.2.0","latest":"0.2.0","versions":["0.2.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{"jsdotlua/jest":{"version":"^3.10.0","alias":"Jest"},"jsdotlua/jest-globals":{"version":"^3.10.0","alias":"JestGlobals"},"jsdotlua/react":{"version":"^17.0.2","alias":"React"},"jsdotlua/react-roblox":{"version":"^17.0.2","alias":"ReactRoblox"}},"integrity":"5df85df05cfd3a46dc0cbad3935b5373f5d325716bff0998daa874d4e6e52ebb","likes":0,"downloads":0,"install":"forest install flipbook-labs/react-testing-library-luau","url":"https://forest.dev/p/roblox/flipbook-labs/react-testing-library-luau","files":"https://api.forest.dev/ai/package/roblox/flipbook-labs/react-testing-library-luau/files","readme":"# react-testing-library-luau\n\n> Idiomatic-Luau testing library for [react-lua](https://github.com/jsdotlua/react-lua)\n> components, running against real Instances in a live DataModel.\n\n```luau\nlocal React = require(Packages.React)\nlocal ReactTesting = require(Packages.ReactTesting)\n\nReactTesting.installCleanup(JestGlobals.afterEach)\n\ntest(\"clicking increments\", function()\n\tlocal function Counter()\n\t\tlocal count, setCount = React.useState(0)\n\t\treturn React.createElement(\"TextButton\", {\n\t\t\tText = `Count: {count}`,\n\t\t\t[React.Event.Activated] = function()\n\t\t\t\tsetCount(count + 1)\n\t\t\tend,\n\t\t})\n\tend\n\n\tlocal result = ReactTesting.render(React.createElement(Counter))\n\n\tReactTesting.fireEvent.activated(result.getByText(\"Count: 0\") :: TextButton)\n\n\texpect(result.getByText(\"Count: 1\")).toBeDefined()\nend)\n```\n\nFull reference: [docs/API.md](docs/API.md). Coming from Roblox's port?\n[docs/migration-from-roblox-rtl.md](docs/migration-from-roblox-rtl.md).\n\n## Why not the existing port?\n\nRoblox's [react-testing-library-lua](https://github.com/Roblox/react-testing-library-lua)\nis a verbatim transpilation of the JS library — and its `fireEvent` drives\n`VirtualInputManager`, a RobloxScriptSecurity service that only exists in\nRoblox's internal test infrastructure. Outside it (plugins, Studio command\nbar, Open Cloud Luau execution), the port cannot simulate events at all.\n\nThis library keeps the Testing Library mental model but is designed for Luau\nand for user-level security:\n\n- **Event dispatch that works everywhere**: React handler invocation through\n  react-roblox's exported test internals, plus real engine signals where Luau\n  can trigger them ([docs/EVENT_DISPATCH.md](docs/EVENT_DISPATCH.md))\n- **`--!strict` throughout; no `any` casts** in library source (CI-enforced);\n  explicit option types instead of merge-based option objects\n- **Roblox event names** (`activated`, `textChanged`, `focus`), not DOM\n  aliases (`click`, `change`)\n- **No global `screen`** — queries come from `render()` results and\n  `within(container)`; Roblox has no global document\n- **No LuauPolyfill / Promise dependencies** — `waitFor` and `findBy*` are\n  plain blocking calls polling with `task.wait`\n\n## Queries\n\n`ByText`, `ByPlaceholderText`, `ByDisplayValue`, and `ByTestId`\n(CollectionService `data-testid=<value>` tags, compatible with the Roblox\nport's convention) — each as `get / getAll / query / queryAll / find /\nfindAll`. `ByRole`/`ByLabelText`/`ByTitle`/`ByAltText` are intentionally\nabsent: Roblox has no accessibility tree.\n\n## Workspace\n\nTwo Loom packages wired with a path dependency:\n\n- [`modules/instance-testing`](modules/instance-testing) — queries over plain\n  Instances (the folded dom-testing-library layer; no React dependency —\n  usable with Roact/Fusion/hand-built UI too)\n- [`modules/react-testing`](modules/react-testing) — render / fireEvent /\n  act / waitFor, re-exporting the queries\n\n## Development\n\n```sh\nrokit install      # toolchain (lute, rojo, darklua, selene, stylua, wally, ...)\nlute run install   # loom + wally dependencies\nlute run lint      # selene + stylua\nlute run analyze   # strict typecheck (luau-lsp, new solver)\nlute run test      # jest via rocale-cli cloud execution (needs ROBLOX_API_KEY in .env)\n```\n\nThe e2e runbook (headless and in-Studio) lives in\n[.agents/skills/e2e/SKILL.md](.agents/skills/e2e/SKILL.md).\n\n## License\n\nMIT. Portions of test suites and query behavior derive from Roblox's\nMIT-licensed testing-library ports — see [LICENSE](LICENSE).\n","readmeTruncated":false}