diff --git a/Makefile b/Makefile
index 3512619a7..d5a930595 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,11 @@ jest: ## Run the jest unit tests
jest-watch: ## Run the jest unit tests in watch mode
@npx jest --watch
+.PHONY: jest-devtools
+jest-devtools: ## Run the jest unit tests in watch mode
+ @echo "open Chrome and go to chrome://inspect"
+ @node --inspect-brk node_modules/.bin/jest --runInBand --detectOpenHandles
+
.PHONY: test
test: ## Run the runtests from dune (snapshot)
@$(DUNE) build @runtest
@@ -54,7 +59,10 @@ format-check: ## Checks if format is correct
.PHONY: install
install: ## Update the package dependencies when new deps are added to dune-project
@opam install . --deps-only --with-test
- @npm install
+# --force is needed because we are installing react@19 while other dependencies
+# require react@18. It's a good workaround to bypass the npm validation error
+# and test the rc versions of React
+ @npm install --force
.PHONY: init
create-switch: ## Create a local opam switch
@@ -62,3 +70,11 @@ create-switch: ## Create a local opam switch
.PHONY: init
init: create-switch install ## Create a local opam switch, install deps
+
+.PHONY: demo-watch
+demo-watch: ## Build the demo in watch mode
+ @$(DUNE) build @melange-app --watch
+
+.PHONY: demo-serve
+demo-serve: ## Build the demo and serve it
+ npx http-server -p 8080 _build/default/demo/
diff --git a/demo/dune b/demo/dune
new file mode 100644
index 000000000..851bbbc10
--- /dev/null
+++ b/demo/dune
@@ -0,0 +1,9 @@
+(melange.emit
+ (target demo)
+ (alias melange-app)
+ (module_systems
+ (es6 mjs))
+ (libraries reason-react melange.belt melange.dom)
+ (runtime_deps index.html)
+ (preprocess
+ (pps melange.ppx reason-react-ppx)))
diff --git a/demo/index.html b/demo/index.html
new file mode 100644
index 000000000..e333157fd
--- /dev/null
+++ b/demo/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+ Demo reason-react
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/main.re b/demo/main.re
new file mode 100644
index 000000000..8994a58dc
--- /dev/null
+++ b/demo/main.re
@@ -0,0 +1,187 @@
+module Stateful = {
+ [@react.component]
+ let make = (~title, ~initialValue=0, ~children=React.null) => {
+ let (value, setValue) = React.useState(() => initialValue);
+ let onClick = _ => setValue(value => value + 1);
+
+
+ {React.string(title)}
+ value->React.int
+ children
+ ;
+ };
+};
+
+module Reducer = {
+ type action =
+ | Increment
+ | Decrement;
+
+ [@react.component]
+ let make = (~initialValue=0) => {
+ let (state, send) =
+ React.useReducer(
+ (state, action) =>
+ switch (action) {
+ | Increment => state + 1
+ | Decrement => state - 1
+ },
+ initialValue,
+ );
+
+ Js.log2("Reducer state", state);
+
+
+ {React.string("React.useReducer")}
+ state->React.int
+ send(Increment)}>
+ "Increment"->React.string
+
+ send(Decrement)}>
+ "Decrement"->React.string
+
+ ;
+ };
+};
+
+module ReducerWithMapState = {
+ type action =
+ | Increment
+ | Decrement;
+
+ [@react.component]
+ let make = (~initialValue=0) => {
+ let (state, send) =
+ React.useReducerWithMapState(
+ (state, action) =>
+ switch (action) {
+ | Increment => state + 1
+ | Decrement => state - 1
+ },
+ initialValue,
+ initialValue => initialValue + 75,
+ );
+
+ Js.log2("ReducerWithMapState state", state);
+
+
+ {React.string("React.useReducerWithMapState")}
+ state->React.int
+ send(Increment)}>
+ "Increment"->React.string
+
+ send(Decrement)}>
+ "Decrement"->React.string
+
+ ;
+ };
+};
+
+module WithEffect = {
+ [@react.component]
+ let make = (~value) => {
+ React.useEffect1(
+ () => {
+ Js.log("useEffect");
+ None;
+ },
+ [|value|],
+ );
+
+ React.string("React.useEffect");
+ };
+};
+
+module RerenderOnEachClick = {
+ [@react.component]
+ let make = (~value=0, ~callback as _) => {
+ let (value, setValue) = React.useState(() => value);
+ let onClick = _ =>
+ if (value < 3) {
+ Js.log2("Clicked with:", value);
+ setValue(value => value + 1);
+ } else {
+ Js.log("Max value reached, not firing a rerender");
+ setValue(value => value);
+ };
+
+
+ {React.string("RerenderOnEachClick")}
+
+ ;
+ };
+};
+
+module WithLayoutEffect = {
+ [@react.component]
+ let make = (~value=0, ~callback) => {
+ React.useLayoutEffect1(
+ () => {
+ callback(value);
+ Js.log("useLayoutEffect");
+ None;
+ },
+ [|value|],
+ );
+
+ {React.string("React.useLayoutEffect")} ;
+ };
+};
+
+module WithRefAndEffect = {
+ [@react.component]
+ let make = (~callback) => {
+ let myRef = React.useRef(1);
+ React.useEffect0(() => {
+ myRef.current = myRef.current + 1;
+ callback(myRef);
+ None;
+ });
+
+
+ {React.string("React.useRef and useEffect")}
+ {React.int(myRef.current)}
+ ;
+ };
+};
+
+[@mel.module "react"]
+external useReducer:
+ ([@mel.uncurry] (('state, 'action) => 'state), 'state) =>
+ ('state, 'action => unit) =
+ "useReducer";
+
+module UseReducerNoProblemo = {
+ [@react.component]
+ let make = () => {
+ let reducer = (v, _) => v + 1;
+ let (state, send) = useReducer(reducer, 0);
+ Js.log("asdfasd");
+ send(0)}> {React.int(state)} ;
+ };
+};
+
+module App = {
+ [@react.component]
+ let make = (~initialValue) => {
+ let value = 99;
+ let callback = _number => ();
+
+
+
+
+
+
+
+
+
+ ;
+ };
+};
+
+switch (ReactDOM.querySelector("#root")) {
+| Some(el) =>
+ let root = ReactDOM.Client.createRoot(el);
+ ReactDOM.Client.render(root, );
+| None => Js.log("No root element found")
+};
diff --git a/dune b/dune
index dc5b54052..5a812ba9c 100644
--- a/dune
+++ b/dune
@@ -1 +1 @@
-(dirs src test ppx)
+(dirs src test ppx demo)
diff --git a/package-lock.json b/package-lock.json
index 56484d8a6..b08e74e85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,10 +9,12 @@
"version": "0.11.0",
"license": "MIT",
"devDependencies": {
+ "@testing-library/dom": "^10.4.0",
+ "@testing-library/react": "^16.0.1",
+ "http-server": "^14.1.1",
"jest": "^26.0.1",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-test-renderer": "^18.2.0"
+ "react": "19.0.0-rc.1",
+ "react-dom": "19.0.0-rc.1"
}
},
"node_modules/@ampproject/remapping": {
@@ -565,6 +567,19 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/template": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
@@ -954,6 +969,82 @@
"@sinonjs/commons": "^1.7.0"
}
},
+ "node_modules/@testing-library/dom": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
+ "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/@testing-library/react": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz",
+ "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": "^10.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -963,6 +1054,13 @@
"node": ">= 6"
}
},
+ "node_modules/@types/aria-query": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/babel__core": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz",
@@ -1198,6 +1296,16 @@
"sprintf-js": "~1.0.2"
}
},
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"node_modules/arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -1243,6 +1351,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/async": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+ "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.14"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1405,6 +1523,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1500,6 +1631,26 @@
"node": ">=0.10.0"
}
},
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1782,6 +1933,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/corser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
+ "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1884,6 +2045,24 @@
"node": ">=0.10.0"
}
},
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
@@ -1906,6 +2085,16 @@
"node": ">=0.4.0"
}
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -1924,6 +2113,13 @@
"node": ">= 10.14.2"
}
},
+ "node_modules/dom-accessibility-api": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/domexception": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
@@ -1987,6 +2183,29 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -2057,6 +2276,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/exec-sh": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz",
@@ -2354,6 +2580,27 @@
"node": ">=8"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -2410,10 +2657,14 @@
}
},
"node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
@@ -2433,6 +2684,26 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@@ -2495,6 +2766,19 @@
"node": ">=4"
}
},
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -2529,6 +2813,45 @@
"node": ">=8"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -2592,6 +2915,29 @@
"node": ">=0.10.0"
}
},
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -2616,6 +2962,21 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
@@ -2630,6 +2991,73 @@
"node": ">= 6"
}
},
+ "node_modules/http-server": {
+ "version": "14.1.1",
+ "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
+ "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "basic-auth": "^2.0.1",
+ "chalk": "^4.1.2",
+ "corser": "^2.0.1",
+ "he": "^1.2.0",
+ "html-encoding-sniffer": "^3.0.0",
+ "http-proxy": "^1.18.1",
+ "mime": "^1.6.0",
+ "minimist": "^1.2.6",
+ "opener": "^1.5.1",
+ "portfinder": "^1.0.28",
+ "secure-compare": "3.0.1",
+ "union": "~0.5.0",
+ "url-join": "^4.0.1"
+ },
+ "bin": {
+ "http-server": "bin/http-server"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/http-server/node_modules/html-encoding-sniffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+ "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/http-server/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/http-server/node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
@@ -3708,18 +4136,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -3729,6 +4145,16 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lz-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
@@ -3826,6 +4252,19 @@
"node": ">=8.6"
}
},
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -3890,6 +4329,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -4041,15 +4493,6 @@
"integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==",
"dev": true
},
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/object-copy": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
@@ -4135,6 +4578,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-inspect": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -4183,6 +4639,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+ "dev": true,
+ "license": "(WTFPL OR MIT)",
+ "bin": {
+ "opener": "bin/opener-bin.js"
+ }
+ },
"node_modules/p-each-series": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
@@ -4345,6 +4811,31 @@
"node": ">=8"
}
},
+ "node_modules/portfinder": {
+ "version": "1.0.32",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
+ "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async": "^2.6.4",
+ "debug": "^3.2.7",
+ "mkdirp": "^0.5.6"
+ },
+ "engines": {
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/portfinder/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
"node_modules/posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -4407,6 +4898,22 @@
"node": ">=6"
}
},
+ "node_modules/qs": {
+ "version": "6.13.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz",
+ "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -4414,69 +4921,41 @@
"dev": true
},
"node_modules/react": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "version": "19.0.0-rc.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.0.0-rc.1.tgz",
+ "integrity": "sha512-NZKln+uyPuyHchzP07I6GGYFxdAoaKhehgpCa3ltJGzwE31OYumLeshGaitA1R/fS5d9D2qpZVwTFAr6zCLM9w==",
"dev": true,
- "dependencies": {
- "loose-envify": "^1.1.0"
- },
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
- "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "version": "19.0.0-rc.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc.1.tgz",
+ "integrity": "sha512-k8MfDX+4G+eaa1cXXI9QF4d+pQtYol3nx8vauqRWUEOPqC7NQn2qmEqUsLoSd28rrZUL+R3T2VC+kZ2Hyx1geQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.0"
+ "scheduler": "0.25.0-rc.1"
},
"peerDependencies": {
- "react": "^18.2.0"
+ "react": "19.0.0-rc.1"
}
},
+ "node_modules/react-dom/node_modules/scheduler": {
+ "version": "0.25.0-rc.1",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc.1.tgz",
+ "integrity": "sha512-fVinv2lXqYpKConAMdergOl5owd0rY1O4P/QTe0aWKCqGtu7VsCt1iqQFxSJtqK4Lci/upVSBpGwVC7eWcuS9Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
},
- "node_modules/react-shallow-renderer": {
- "version": "16.15.0",
- "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
- "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==",
- "dev": true,
- "dependencies": {
- "object-assign": "^4.1.1",
- "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
- },
- "peerDependencies": {
- "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
- }
- },
- "node_modules/react-test-renderer": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz",
- "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==",
- "dev": true,
- "dependencies": {
- "react-is": "^18.2.0",
- "react-shallow-renderer": "^16.15.0",
- "scheduler": "^0.23.0"
- },
- "peerDependencies": {
- "react": "^18.2.0"
- }
- },
- "node_modules/react-test-renderer/node_modules/react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
- "dev": true
- },
"node_modules/read-pkg": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
@@ -4527,6 +5006,13 @@
"node": ">=8"
}
},
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@@ -4663,6 +5149,13 @@
"node": "6.* || >= 7.*"
}
},
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
@@ -4984,14 +5477,12 @@
"node": ">=10"
}
},
- "node_modules/scheduler": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "node_modules/secure-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
+ "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
"dev": true,
- "dependencies": {
- "loose-envify": "^1.1.0"
- }
+ "license": "MIT"
},
"node_modules/semver": {
"version": "6.3.1",
@@ -5008,6 +5499,24 @@
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"dev": true
},
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -5072,6 +5581,25 @@
"dev": true,
"optional": true
},
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
@@ -5756,6 +6284,18 @@
"is-typedarray": "^1.0.0"
}
},
+ "node_modules/union": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
+ "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
+ "dev": true,
+ "dependencies": {
+ "qs": "^6.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/union-value": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@@ -5874,6 +6414,13 @@
"deprecated": "Please see https://github.com/lydell/urix#deprecated",
"dev": true
},
+ "node_modules/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/url-parse": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
diff --git a/package.json b/package.json
index 63bf49935..f6f991768 100644
--- a/package.json
+++ b/package.json
@@ -26,9 +26,11 @@
"homepage": "https://reasonml.github.io/reason-react/",
"devDependencies": {
"jest": "^26.0.1",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-test-renderer": "^18.2.0"
+ "react": "19.0.0-rc.1",
+ "react-dom": "19.0.0-rc.1",
+ "@testing-library/dom": "^10.4.0",
+ "@testing-library/react": "^16.0.1",
+ "http-server": "^14.1.1"
},
"jest": {
"moduleDirectories": [
diff --git a/src/React.re b/src/React.re
index 431b7a05a..ae8cd326e 100644
--- a/src/React.re
+++ b/src/React.re
@@ -885,6 +885,12 @@ external startTransition: ([@mel.uncurry] (unit => unit)) => unit =
external useDebugValue: ('value, ~format: 'value => string=?, unit) => unit =
"useDebugValue";
+[@mel.module "react"]
+external act: (unit => unit) => Js.Promise.t(unit) = "act";
+[@mel.module "react"]
+external actAsync: (unit => Js.Promise.t(unit)) => Js.Promise.t(unit) =
+ "act";
+
module Experimental = {
/* This module is used to bind to APIs for future versions of React. There is no guarantee of backwards compatibility or stability. */
/* https://react.dev/reference/react/use */
diff --git a/src/React.rei b/src/React.rei
index 372337618..66b4de0ee 100644
--- a/src/React.rei
+++ b/src/React.rei
@@ -573,6 +573,12 @@ external startTransition: ([@mel.uncurry] (unit => unit)) => unit =
external useTransition: unit => (bool, callback(callback(unit, unit), unit)) =
"useTransition";
+[@mel.module "react"]
+external act: (unit => unit) => Js.Promise.t(unit) = "act";
+[@mel.module "react"]
+external actAsync: (unit => Js.Promise.t(unit)) => Js.Promise.t(unit) =
+ "act";
+
module Experimental: {
/* This module is used to bind to APIs for future versions of React. There is no guarantee of backwards compatibility or stability. */
[@mel.module "react"] external usePromise: Js.Promise.t('a) => 'a = "use";
diff --git a/src/ReactTestRenderer.re b/src/ReactTestRenderer.re
deleted file mode 100644
index 2c3494447..000000000
--- a/src/ReactTestRenderer.re
+++ /dev/null
@@ -1,24 +0,0 @@
-type t;
-
-[@mel.module "react-test-renderer"]
-external create: React.element => t = "create";
-
-[@mel.send] external toJSON: t => Js.Json.t = "toJSON";
-[@mel.send] external toObject: t => Js.t({..}) = "%identity";
-
-module Shallow = {
- type t;
-
- [@mel.module "react-test-renderer/shallow"]
- external createRenderer: unit => t = "createRenderer";
-
- [@mel.send]
- external render: (t, React.element) => option(React.element) = "render";
-
- [@mel.send]
- external getRenderOutput: t => option(React.element) = "getRenderOutput";
-
- [@mel.send] external unmount: t => unit = "unmount";
-
- let renderWithRenderer = render(createRenderer());
-};
diff --git a/src/ReactTestRenderer.rei b/src/ReactTestRenderer.rei
deleted file mode 100644
index c68d57b71..000000000
--- a/src/ReactTestRenderer.rei
+++ /dev/null
@@ -1,24 +0,0 @@
-type t;
-
-[@mel.module "react-test-renderer"]
-external create: React.element => t = "create";
-
-[@mel.send] external toJSON: t => Js.Json.t = "toJSON";
-[@mel.send] external toObject: t => Js.t({..}) = "%identity";
-
-module Shallow: {
- type t;
-
- [@mel.module "react-test-renderer/shallow"]
- external createRenderer: unit => t = "createRenderer";
-
- [@mel.send]
- external render: (t, React.element) => option(React.element) = "render";
-
- [@mel.send]
- external getRenderOutput: t => option(React.element) = "getRenderOutput";
-
- [@mel.send] external unmount: t => unit = "unmount";
-
- let renderWithRenderer: React.element => option(React.element);
-};
diff --git a/src/dune b/src/dune
index 1226d33d9..91ba8d459 100644
--- a/src/dune
+++ b/src/dune
@@ -9,7 +9,6 @@
ReactDOM
ReactDOMServer
ReactDOMTestUtils
- ReactTestRenderer
ReasonReactRouter
ReasonReactErrorBoundary)
(preprocess
diff --git a/test/Form__test.re b/test/Form__test.re
index 123f47ad7..dbbe7eee2 100644
--- a/test/Form__test.re
+++ b/test/Form__test.re
@@ -1,15 +1,7 @@
-[@alert "-deprecated"];
-
open Jest;
-open Jest.Expect;
-open ReactDOMTestUtils;
-open Belt;
module FormData = React.Experimental.FormData;
-/* https://react.dev/blog/2022/03/08/react-18-upgrade-guide#configuring-your-testing-environment */
-[%%mel.raw "globalThis.IS_REACT_ACT_ENVIRONMENT = true"];
-
type message = {
text: string,
sending: bool,
@@ -55,24 +47,26 @@ module Thread = {
};
};
<>
- {{
- optimisticMessages->Belt.List.map(message =>
-
- {React.string(message.text)}
- {message.sending
- ? React.null
- : {React.string("(Enviando...)")} }
-
- );
- }
- ->Belt.List.toArray
- ->React.array}
+
+ {{
+ optimisticMessages->Belt.List.map(message =>
+
+ {React.string(message.text)}
+ {message.sending
+ ? React.null
+ : {React.string("(Enviando...)")} }
+
+ );
+ }
+ ->Belt.List.toArray
+ ->React.array}
+
{React.cloneElement(
ReactDOM.createElement(
"form",
~props=ReactDOM.domProps(~ref=ReactDOM.Ref.domRef(formRef), ()),
[|
- ,
+ ,
{React.string("Enviar")} ,
|],
),
@@ -93,7 +87,7 @@ module App = {
React.useState(() =>
[
{
- text: "¡Hola!",
+ text: {j|¡Hola!|j},
sending: false,
key: 1,
},
@@ -129,46 +123,37 @@ module App = {
};
};
-describe("Form with useOptimistic", () => {
- let container = ref(None);
+let (let.await) = (p, f) => Js.Promise.then_(f, p);
- beforeEach(prepareContainer(container));
- afterEach(cleanupContainer(container));
+let findByString = (text, container) =>
+ ReactTestingLibrary.findByText(~matcher=`Str(text), container);
- test("should render the form", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
+let findByPlaceholderText = (text, container) =>
+ ReactTestingLibrary.findByPlaceholderText(~matcher=`Str(text), container);
- act(() => ReactDOM.Client.render(root, ));
+describe("Form with useOptimistic", () => {
+ testPromise("should render the form", finish => {
+ let container = ReactTestingLibrary.render( );
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "0")
- ->Option.isSome,
- )
- ->toBe(true);
+ ReactTestingLibrary.actAsync(() => {
+ let.await _ = findByString({j|¡Hola!|j}, container);
- let button = container->DOM.findBySelector("button");
+ let.await button = findByString("Enviar", container);
+ let.await input = findByPlaceholderText("message", container);
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
+ FireEvent.change(
+ input,
+ ~eventInit={
+ "target": {
+ "value": "Let's go!",
+ },
+ },
+ );
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "0")
- ->Option.isSome,
- )
- ->toBe(false);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "1")
- ->Option.isSome,
- )
- ->toBe(true);
- });
+ FireEvent.click(button);
+ let.await _newMessage = findByString("Let's go!", container);
+ /* If the promise resolve, means the node is found in the DOM */
+ finish();
+ });
+ })
});
diff --git a/test/Hooks__test.re b/test/Hooks__test.re
index 41a5e1fed..71aa3dc4a 100644
--- a/test/Hooks__test.re
+++ b/test/Hooks__test.re
@@ -1,12 +1,5 @@
-[@alert "-deprecated"];
-
open Jest;
open Jest.Expect;
-open ReactDOMTestUtils;
-open Belt;
-
-/* https://react.dev/blog/2022/03/08/react-18-upgrade-guide#configuring-your-testing-environment */
-[%%mel.raw "globalThis.IS_REACT_ACT_ENVIRONMENT = true"];
type store('a) = {
subscribe: (unit => unit, unit) => unit,
@@ -59,11 +52,33 @@ let store = (initialState: 'a) => {
module DummyStatefulComponent = {
[@react.component]
let make = (~initialValue=0, ()) => {
- let (value, setValue) = React.useState(() => initialValue);
+ let (value, setValue) = React.Uncurried.useState(() => initialValue);
+ let onClick = _ => setValue(. value => value + 1);
+ {React.int(value)} ;
+ };
+};
+
+module DummyIncrementReducerComponent = {
+ type action =
+ | Increment;
+
+ [@react.component]
+ let make = (~initialValue=0) => {
+ let (state, send) =
+ React.Uncurried.useReducer(
+ (state, action) =>
+ switch (action) {
+ | Increment => state + 1
+ },
+ initialValue,
+ );
- setValue(value => value + 1)}>
- value->React.int
- ;
+
+ {React.int(state)}
+ {send(. Increment)}}>
+ {React.string("Increment")}
+
+ ;
};
};
@@ -71,10 +86,11 @@ module DummyReducerComponent = {
type action =
| Increment
| Decrement;
+
[@react.component]
- let make = (~initialValue=0, ()) => {
+ let make = (~initialValue=0) => {
let (state, send) =
- React.useReducer(
+ React.Uncurried.useReducer(
(state, action) =>
switch (action) {
| Increment => state + 1
@@ -83,13 +99,15 @@ module DummyReducerComponent = {
initialValue,
);
+ Js.log2("state", state);
+
<>
- state->React.int
- send(Increment)}>
- "Increment"->React.string
+ {React.int(state)}
+ send(. Increment)}>
+ {React.string("Increment")}
- send(Decrement)}>
- "Decrement"->React.string
+ send(. Decrement)}>
+ {React.string("Decrement")}
>;
};
@@ -99,10 +117,11 @@ module DummyReducerWithMapStateComponent = {
type action =
| Increment
| Decrement;
+
[@react.component]
let make = (~initialValue=0, ()) => {
let (state, send) =
- React.useReducerWithMapState(
+ React.Uncurried.useReducerWithMapState(
(state, action) =>
switch (action) {
| Increment => state + 1
@@ -112,21 +131,21 @@ module DummyReducerWithMapStateComponent = {
initialValue => initialValue + 1,
);
- <>
- state->React.int
- send(Increment)}>
- "Increment"->React.string
+
+ state->React.int
+ send(. Increment)}>
+ {React.string("Increment")}
- send(Decrement)}>
- "Decrement"->React.string
+ send(. Decrement)}>
+ {React.string("Decrement")}
- >;
+ ;
};
};
-module DummyComponentWithEffect = {
+module WithEffect = {
[@react.component]
- let make = (~value=0, ~callback, ()) => {
+ let make = (~value, ~callback) => {
React.useEffect1(
() => {
callback(value);
@@ -135,7 +154,26 @@ module DummyComponentWithEffect = {
[|value|],
);
-
;
+ {React.int(value)} ;
+ };
+};
+
+module RerenderOnEachClick = {
+ [@react.component]
+ let make = (~initialValue=0, ~maxValue=3, ~callback) => {
+ let (value, setValue) = React.Uncurried.useState(() => initialValue);
+ let onClick = _ =>
+ if (value < maxValue) {
+ setValue(. value => value + 1);
+ } else {
+ /* Fire a setState with the same value */
+ setValue(. value => value);
+ };
+
+
+ {React.string("RerenderOnEachClick")}
+
+ ;
};
};
@@ -156,7 +194,7 @@ module DummyComponentWithLayoutEffect = {
module DummyComponentWithRefAndEffect = {
[@react.component]
- let make = (~callback, ()) => {
+ let make = (~callback) => {
let myRef = React.useRef(1);
React.useEffect0(() => {
myRef.current = myRef.current + 1;
@@ -167,311 +205,185 @@ module DummyComponentWithRefAndEffect = {
};
};
-describe("Hooks", () => {
- let container = ref(None);
+let getByString = (text, container) =>
+ ReactTestingLibrary.getByText(~matcher=`Str(text), container);
- beforeEach(prepareContainer(container));
- afterEach(cleanupContainer(container));
+let findByPlaceholderText = (text, container) =>
+ ReactTestingLibrary.findByPlaceholderText(~matcher=`Str(text), container);
- test("can render react components", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
+[@mel.get] external tagName: Dom.element => string = "tagName";
+[@mel.get] external innerHTML: Dom.element => string = "innerHTML";
- act(() => ReactDOM.Client.render(root, ));
+let getByTag = (tag, container) => {
+ let fn = (_string, element: Dom.element) => {
+ element->tagName->Js.String.toLowerCase == tag;
+ };
+ ReactTestingLibrary.getByText(~matcher=`Func(fn), container);
+};
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "0")
- ->Option.isSome,
- )
- ->toBe(true);
+let getByRole = (role, container) => {
+ ReactTestingLibrary.getByRole(~matcher=`Str(role), container);
+};
- let button = container->DOM.findBySelector("button");
+let getByInnerHTML = (text, container) => {
+ let fn = (inner, _element: Dom.element) => {
+ String.equal(inner, text);
+ };
+ ReactTestingLibrary.getByText(~matcher=`Func(fn), container);
+};
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
+describe("Hooks", () => {
+ beforeEach(() => ReactTestingLibrary.cleanup());
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "0")
- ->Option.isSome,
- )
- ->toBe(false);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent("button", "1")
- ->Option.isSome,
- )
- ->toBe(true);
+ test("can render react components", () => {
+ let container = ReactTestingLibrary.render( );
+ let button = getByTag("button", container);
+ expect(DomTestingLibrary.getNodeText(button))->toBe("0");
+ FireEvent.click(button);
+ expect(DomTestingLibrary.getNodeText(button))->toBe("1");
});
- test("can render react components with reducers", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {ReactDOM.Client.render(root, )});
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "0")
- ->Option.isSome,
- )
- ->toBe(true);
-
- let button =
- container->DOM.findBySelectorAndPartialTextContent(
- "button",
- "Increment",
+ test("can render react components with effects", () => {
+ let container =
+ ReactTestingLibrary.render(
+ ()} />,
);
+ let button = getByTag("button", container);
+ let counter = getByTag("span", container);
+ FireEvent.click(button); /* 0 -> 1 */
+ expect(DomTestingLibrary.getNodeText(counter))->toBe("1");
+ FireEvent.click(button); /* 1 -> 2 */
+ expect(DomTestingLibrary.getNodeText(counter))->toBe("2");
+ /* Limit reached, counter doesn't increase, so no rerenders */
+ FireEvent.click(button); /* 2 -> 2 */
+ expect(DomTestingLibrary.getNodeText(counter))->toBe("2");
+ });
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
+ test("can render react components with effects", () => {
+ let callback = Mock.fn();
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "0")
- ->Option.isSome,
- )
- ->toBe(false);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "1")
- ->Option.isSome,
- )
- ->toBe(true);
-
- let button =
- container->DOM.findBySelectorAndPartialTextContent(
- "button",
- "Decrement",
+ let container =
+ ReactTestingLibrary.render(
+ ,
);
-
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "0")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "1")
- ->Option.isSome,
- )
- ->toBe(false);
+ let button = getByTag("button", container);
+ FireEvent.click(button); /* 0 -> 1 */
+ FireEvent.click(button); /* 1 -> 2 */
+ /* Limit reached, counter doesn't increase, so no rerenders */
+ FireEvent.click(button); /* 2 -> 2 */
+ FireEvent.click(button); /* 2 -> 2 */
+
+ let allCalls = callback->Mock.getMock->Mock.calls;
+ expect(allCalls)->toEqual([|[|0|], [|1|], [|2|]|]);
});
- test("can render react components with reducers (map state)", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
+ test("useSyncExternalStore", () => {
+ let mock = Mock.fn();
+ let {subscribe, getState, setState} = store("initial");
- act(() => {
- ReactDOM.Client.render(root, )
- });
+ let subscribeWithMock = args => {
+ let _ = mock(.);
+ subscribe(args);
+ };
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "1")
- ->Option.isSome,
- )
- ->toBe(true);
-
- let button =
- container->DOM.findBySelectorAndPartialTextContent(
- "button",
- "Increment",
- );
+ module App = {
+ [@react.component]
+ let make = () => {
+ let snapshot =
+ React.useSyncExternalStore(
+ ~subscribe=subscribeWithMock,
+ ~getSnapshot=getState,
+ );
+ {React.string(snapshot)} ;
+ };
+ };
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
+ let container = ReactTestingLibrary.render( );
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "1")
- ->Option.isSome,
- )
- ->toBe(false);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "2")
- ->Option.isSome,
- )
- ->toBe(true);
-
- let button =
- container->DOM.findBySelectorAndPartialTextContent(
- "button",
- "Decrement",
- );
+ /* Ensure initial value is passed */
+ let span = getByTag("span", container);
+ expect(DomTestingLibrary.getNodeText(span))->toBe("initial");
- act(() => {
- switch (button) {
- | Some(button) => Simulate.click(button)
- | None => ()
- }
- });
+ ReactTestingLibrary.act(() => setState("changed"));
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "1")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent(".value", "2")
- ->Option.isSome,
- )
- ->toBe(false);
- });
+ /* Ensure store is being updated */
+ let nextState = getState();
+ expect(nextState)->toBe("changed");
- test("can render react components with effects", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
- let callback = Mock.fn();
+ /* the state should be propagated to App */
+ expect(DomTestingLibrary.getNodeText(span))->toBe("changed");
- act(() => {
- ReactDOM.Client.render(
- root,
- ,
- )
- });
- act(() => {
- ReactDOM.Client.render(
- root,
- ,
- )
- });
- act(() => {
- ReactDOM.Client.render(
- root,
- ,
- )
- });
+ /* on the next render */
+ ReactTestingLibrary.rerender( , container);
- expect(callback->Mock.getMock->Mock.calls)->toEqual([|[|0|], [|1|]|]);
+ /* the state should stay 'changed' */
+ expect(DomTestingLibrary.getNodeText(span))->toBe("changed");
});
test("can render react components with layout effects", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
let callback = Mock.fn();
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
,
- )
- });
- act(() => {
- ReactDOM.Client.render(
- root,
+ );
+
+ ReactTestingLibrary.act(() => {
+ ReactTestingLibrary.rerender(
,
+ container,
)
});
- act(() => {
- ReactDOM.Client.render(
- root,
+ ReactTestingLibrary.act(() => {
+ ReactTestingLibrary.rerender(
,
+ container,
)
});
-
expect(callback->Mock.getMock->Mock.calls)->toEqual([|[|0|], [|1|]|]);
});
test("can work with useRef", () => {
- let container = getContainer(container);
let myRef = ref(None);
let callback = reactRef => {
myRef := Some(reactRef);
};
- let root = ReactDOM.Client.createRoot(container);
- act(() => {
- ReactDOM.Client.render(
- root,
- ,
- )
- });
+ let _ =
+ ReactTestingLibrary.render( );
- expect(myRef.contents->Option.map(item => item.current))
- ->toEqual(Some(2));
- });
-
- testAsync("useSyncExternalStore", finish => {
- let {subscribe, getState, setState} = store("initial");
- let mock = Mock.fn();
-
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- let subscribeWithMock = args => {
- let _ = mock(.);
- subscribe(args);
- };
-
- module App = {
- [@react.component]
- let make = () => {
- let snapshot =
- React.useSyncExternalStore(
- ~subscribe=subscribeWithMock,
- ~getSnapshot=getState,
- );
- {React.string(snapshot)} ;
- };
+ switch (myRef.contents) {
+ | Some(ref) => expect(ref.current)->toBe(2)
+ | None => failwith("no ref")
};
+ });
- act(() => ReactDOM.Client.render(root, ));
+ test("can render react components with reducers", () => {
+ let container =
+ ReactTestingLibrary.render(
+ ,
+ );
- /* Ensure initial value is passed */
- expect(
- container
- ->DOM.findBySelectorAndTextContent("span", "initial")
- ->Option.isSome,
- )
- ->toBe(true);
+ let counter = getByTag("main", container);
+ let button = getByTag("button", container);
+ expect(counter->innerHTML)->toBe("0");
+ FireEvent.click(button);
+ expect(counter->innerHTML)->toBe("1");
+ });
- act(() => setState("changed"));
+ test("can render react components with reducers and initial map state", () => {
+ let container =
+ ReactTestingLibrary.render( );
- /* Ensure store is being updated */
- let nextState = getState();
- expect(nextState)->toBe("changed");
+ let counter = getByRole("Counter", container);
+ expect(counter->innerHTML)->toBe("1");
- /* on next render */
- act(() => ReactDOM.Client.render(root, ));
+ let incrementButton = getByRole("Increment", container);
+ FireEvent.click(incrementButton);
+ expect(counter->innerHTML)->toBe("2");
- /* the state should be propagated to App */
- expect(
- container
- ->DOM.findBySelectorAndTextContent("span", "changed")
- ->Option.isSome,
- )
- ->toBe(true);
-
- finish();
+ let decrementButton = getByRole("Decrement", container);
+ FireEvent.click(decrementButton);
+ expect(counter->innerHTML)->toBe("1");
});
});
diff --git a/test/ReactRouter__test.re b/test/ReactRouter__test.re
index ed0900d1d..f69471371 100644
--- a/test/ReactRouter__test.re
+++ b/test/ReactRouter__test.re
@@ -4,14 +4,22 @@ open ReasonReactRouter;
describe("it allows to create url from string", () => {
test("it supports basic paths", () => {
- let expected = {path: ["foo", "bar"], hash: "", search: ""};
+ let expected = {
+ path: ["foo", "bar"],
+ hash: "",
+ search: "",
+ };
let generated = dangerouslyGetInitialUrl(~serverUrlString="/foo/bar", ());
expect(generated == expected)->toBe(true);
});
test("it creates with search", () => {
- let expected = {path: ["foo", "bar"], hash: "", search: "q=term"};
+ let expected = {
+ path: ["foo", "bar"],
+ hash: "",
+ search: "q=term",
+ };
let generated =
dangerouslyGetInitialUrl(~serverUrlString="/foo/bar?q=term", ());
diff --git a/test/ReactTestRenderer__test.re b/test/ReactTestRenderer__test.re
deleted file mode 100644
index 2db87305d..000000000
--- a/test/ReactTestRenderer__test.re
+++ /dev/null
@@ -1,106 +0,0 @@
-open Jest;
-
-module Tester = {
- [@react.component]
- let make = () => {React.string("Tester")}
;
-};
-
-describe("ReactTestRenderer", () => {
- open Expect;
-
- test("create returns ReactTestInstance", () => {
- let component = ReactTestRenderer.create( );
- let keys = Js.Obj.keys(ReactTestRenderer.toObject(component));
-
- expect(keys)
- ->toEqual(
- arrayContaining([|
- "_Scheduler",
- "root",
- "toJSON",
- "toTree",
- "update",
- "unmount",
- "unstable_flushSync",
- "getInstance",
- |]),
- );
- });
-
- test("toJSON returns test rendered JSON", () => {
- let component = ReactTestRenderer.create( );
- let json = ReactTestRenderer.toJSON(component);
- let expected =
- Js.Json.parseExn(
- {|
- {
- "type": "div",
- "props": {},
- "children": [ "Tester" ]
- }
- |},
- );
- expect(json == expected)->toBe(true);
- });
-});
-
-let element = {React.string("Tester")}
;
-
-describe("reactShallowRenderer", () => {
- open Expect;
-
- test("createRenderer", () => {
- let renderer = ReactTestRenderer.Shallow.createRenderer();
- let isDefined =
- renderer
- |> Js.Undefined.return
- |> Js.Undefined.toOption
- |> Option.is_some;
- expect(isDefined)->toBe(true);
- });
-
- test("render accepts renderer", () => {
- let renderer = ReactTestRenderer.Shallow.createRenderer();
- let render = ReactTestRenderer.Shallow.render(renderer);
- expect(Js.typeof(render))->toEqual("function");
- });
-
- test("render will render a component", () => {
- let renderer = ReactTestRenderer.Shallow.createRenderer();
- let component =
- ReactTestRenderer.Shallow.render(renderer, )->Option.get;
- expect(component == element)->toBe(true);
- });
-
- test("renderWithRenderer will render a component", () => {
- let component =
- ReactTestRenderer.Shallow.renderWithRenderer( )->Option.get;
-
- expect(component == element)->toBe(true);
- });
-
- test("getRenderOutput returns element", () => {
- let renderer = ReactTestRenderer.Shallow.createRenderer();
-
- ReactTestRenderer.Shallow.render(renderer, ) |> ignore;
-
- let component =
- ReactTestRenderer.Shallow.getRenderOutput(renderer)->Option.get;
-
- expect(component == element)->toBe(true);
- });
-
- test("unmount removes the node", () => {
- let renderer = ReactTestRenderer.Shallow.createRenderer();
-
- ReactTestRenderer.Shallow.render(renderer, ) |> ignore;
- ReactTestRenderer.Shallow.unmount(renderer);
-
- let component =
- ReactTestRenderer.Shallow.getRenderOutput(renderer)
- ->Option.get
- ->Js.Null.return;
-
- expect(component)->toEqual(Js.null);
- });
-});
diff --git a/test/React__test.re b/test/React__test.re
index 1866e07e2..184716112 100644
--- a/test/React__test.re
+++ b/test/React__test.re
@@ -1,12 +1,5 @@
-[@alert "-deprecated"];
-
open Jest;
-open Jest.Expect;
-open ReactDOMTestUtils;
-open Belt;
-
-/* https://react.dev/blog/2022/03/08/react-18-upgrade-guide#configuring-your-testing-environment */
-[%%mel.raw "globalThis.IS_REACT_ACT_ENVIRONMENT = true"];
+open Expect;
module ComponentThatThrows = {
exception TestError;
@@ -28,7 +21,7 @@ module DummyComponentThatMapsChildren = {
element,
{
"key": string_of_int(index),
- "data-index": index,
+ "role": Int.to_string(index),
},
)
})}
@@ -47,151 +40,121 @@ module DummyContext = {
[@react.component]
let make = () => {
let value = React.useContext(context);
- value->React.int
;
+ value->React.int
;
};
};
};
-describe("React", () => {
- let container = ref(None);
+[@mel.get] external tagName: Dom.element => string = "tagName";
+[@mel.get] external innerHTML: Dom.element => string = "innerHTML";
+[@mel.set] external setInnerHTML: (Dom.element, string) => unit = "innerHTML";
+
+let getByRole = (role, container) => {
+ ReactTestingLibrary.getByRole(~matcher=`Str(role), container);
+};
+
+let getByTag = (tag, container) => {
+ let fn = (_string, element: Dom.element) => {
+ element->tagName->Js.String.toLowerCase == tag;
+ };
+ ReactTestingLibrary.getByText(~matcher=`Func(fn), container);
+};
+
+[@mel.send]
+external getAttribute: (Dom.element, string) => option(string) =
+ "getAttribute";
+[@mel.set] external setTitle: (Dom.element, string) => unit = "title";
+[@mel.get] external getTitle: Dom.element => string = "title";
- beforeEach(prepareContainer(container));
- afterEach(cleanupContainer(container));
+let (let.await) = (p, f) => Js.Promise.then_(f, p);
+external createElement: string => Dom.element = "document.createElement";
+[@mel.send]
+external appendChild: (Dom.element, Dom.element) => unit = "appendChild";
+external document: Dom.element = "document";
+external body: Dom.element = "document.body";
+external querySelector: (string, Dom.element) => option(Dom.element) =
+ "document.querySelector";
+
+[@mel.new]
+external mouseEvent: (string, Js.t('a)) => Dom.event = "MouseEvent";
+
+[@mel.send]
+external dispatchEvent: (Dom.element, Dom.event) => unit = "dispatchEvent";
+
+describe("React", () => {
test("can render DOM elements", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(root, "Hello world!"->React.string
)
- });
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent("div", "Hello world!")
- ->Option.isSome,
- )
- ->toBe(true);
+ let container =
+ ReactTestingLibrary.render(
);
+ let div = getByRole("display", container);
+ expect(div->innerHTML)->toBe(" ");
});
test("can render null elements", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => ReactDOM.Client.render(root, React.null
));
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "")
- ->Option.isSome,
- )
- ->toBe(true);
+ let container =
+ ReactTestingLibrary.render( React.null
);
+ let div = getByRole("display", container);
+ expect(div->innerHTML)->toBe("");
});
test("can render string elements", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(root, "Hello"->React.string
)
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "Hello")
- ->Option.isSome,
- )
- ->toBe(true);
+ let container =
+ ReactTestingLibrary.render(
+ "Hello world!"->React.string
,
+ );
+ let div = getByRole("display", container);
+ expect(div->innerHTML)->toBe("Hello world!");
});
test("can render int elements", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => ReactDOM.Client.render(root, 12345->React.int
));
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "12345")
- ->Option.isSome,
- )
- ->toBe(true);
+ let container =
+ ReactTestingLibrary.render(
+ 12345->React.int
,
+ );
+ let div = getByRole("display", container);
+ expect(div->innerHTML)->toBe("12345");
});
test("can render float elements", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(root, 12.345->React.float
)
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "12.345")
- ->Option.isSome,
- )
- ->toBe(true);
+ let container =
+ ReactTestingLibrary.render(
+ 12.345->React.float
,
+ );
+ let div = getByRole("display", container);
+ expect(div->innerHTML)->toBe("12.345");
});
test("can render array of elements", () => {
- let container = getContainer(container);
let array =
- [|1, 2, 3|]
- ->Array.map(item => {
- item->React.int
- });
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(root, array->React.array
)
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "1")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "2")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "3")
- ->Option.isSome,
- )
- ->toBe(true);
+ Array.map(
+ item => {
+
+ item->React.int
+
+ },
+ [|1, 2, 3|],
+ );
+ let container =
+ ReactTestingLibrary.render( {React.array(array)}
);
+ let div = getByRole("1", container);
+ expect(div->innerHTML)->toBe("1");
+ let div = getByRole("2", container);
+ expect(div->innerHTML)->toBe("2");
+ let div = getByRole("3", container);
+ expect(div->innerHTML)->toBe("3");
});
- test("can clone an element", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(
- root,
+ test("can clone an element with data-* attributes", () => {
+ let container =
+ ReactTestingLibrary.render(
React.cloneElement(
"Hello"->React.string
,
{"data-name": "World"},
),
- )
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent(
- "div[data-name='World']",
- "Hello",
- )
- ->Option.isSome,
- )
- ->toBe(true);
+ );
+ let output = ReactTestingLibrary.container(container)->innerHTML;
+ let found = Js.String.includes(~search="data-name=\"World\"", output);
+ expect(found)->toBe(true);
});
test("can work with React refs", () => {
@@ -202,112 +165,70 @@ describe("React", () => {
});
test("Children", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
1->React.int
2->React.int
3->React.int
,
- )
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div[data-index='0']", "1")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div[data-index='1']", "2")
- ->Option.isSome,
- )
- ->toBe(true);
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div[data-index='2']", "3")
- ->Option.isSome,
- )
- ->toBe(true);
+ );
+
+ let div = getByRole("0", container);
+ expect(div->innerHTML)->toBe("1");
+ let div = getByRole("1", container);
+ expect(div->innerHTML)->toBe("2");
+ let div = getByRole("2", container);
+ expect(div->innerHTML)->toBe("3");
});
test("Context", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
,
- )
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "10")
- ->Option.isSome,
- )
- ->toBe(true);
+ );
+
+ expect(getByRole("value", container)->innerHTML)->toBe("10");
});
test("Events", () => {
- let container = getContainer(container);
let value = ref("");
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
{value := event->React.Event.Form.target##value}}
/>,
- )
- });
-
- switch (container->DOM.findBySelector("input[name='test-input']")) {
- | Some(input) => input->Simulate.changeWithValue("My value")
- | None => ()
- };
-
- expect(value.contents)->toEqual("My value");
+ );
+
+ let input = getByRole("input", container);
+ FireEvent.change(
+ input,
+ ~eventInit={
+ "target": {
+ "value": "Let's go!",
+ },
+ },
+ );
+
+ expect(value.contents)->toEqual("Let's go!");
});
test("React.Fragment with key", () => {
- let container = getContainer(container);
let title = Some("foo");
- let root = ReactDOM.Client.createRoot(container);
-
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
- "Child"->React.string
+ "Child"->React.string
,
- )
- });
-
- expect(
- container
- ->DOM.findBySelectorAndPartialTextContent("div", "Child")
- ->Option.isSome,
- )
- ->toBe(true);
+ );
+
+ expect(getByRole("child", container)->innerHTML)->toBe("Child");
});
test("Type inference with keys", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
module Author = {
type t = {
name: string,
@@ -320,27 +241,139 @@ describe("React", () => {
;
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
render({
name: "Joe",
imageUrl: "https://foo.png",
}),
- )
- });
+ );
+ let image = getByRole("img", container);
+ expect(image->getAttribute("src"))->toEqual(Some("https://foo.png"));
+ });
+
+ module Counter = {
+ [@react.component]
+ let make = () => {
+ let (count, setCount) = React.Uncurried.useState(() => 0);
+
+ React.useEffect1(
+ () => {
+ document->setTitle(
+ "You clicked " ++ Int.to_string(count) ++ " times",
+ );
+ None;
+ },
+ [|count|],
+ );
+
+
+ setCount(. prev => prev + 1)}>
+ {React.string("Increment")}
+
+ {React.string(string_of_int(count))}
+
;
+ };
+ };
- expect(container->DOM.findBySelector("img")->Option.isSome)->toBe(true);
+ testPromise("act", finish => {
+ /* This test doesn't use ReactTestingLibrary to test the act API, and the code comes from
+ https://react.dev/reference/react/act example */
+
+ let container: Dom.element = createElement("div");
+ body->appendChild(container);
+
+ let.await () =
+ React.act(() => {
+ let root = ReactDOM.Client.createRoot(container);
+ ReactDOM.Client.render(root, );
+ });
+
+ let valueElement = querySelector(".Value", container);
+ switch (valueElement) {
+ | Some(value) => expect(value->innerHTML)->toBe("0")
+ | None => failwith("Can't find 'Value' element")
+ };
+
+ let title = getTitle(document);
+ expect(title)->toBe("You clicked 0 times");
+
+ let.await () =
+ React.act(() => {
+ let buttonElement = querySelector(".Increment", container);
+ switch (buttonElement) {
+ | Some(button) =>
+ dispatchEvent(button, mouseEvent("click", {"bubbles": true}))
+ | None => failwith("Can't find 'Increment' button")
+ };
+ });
+
+ let valueElement = querySelector(".Value", container);
+ switch (valueElement) {
+ | Some(value) => expect(value->innerHTML)->toBe("1")
+ | None => failwith("Can't find 'Value' element")
+ };
+
+ let title = getTitle(document);
+ expect(title)->toBe("You clicked 1 times");
+
+ finish();
+ });
+
+ testPromise("actAsync", finish => {
+ /* This test doesn't use ReactTestingLibrary to test the act API, and the code comes from
+ https://react.dev/reference/react/act example */
+
+ body->setInnerHTML("");
+ let container: Dom.element = createElement("div");
+ body->appendChild(container);
+
+ let.await () =
+ React.actAsync(() => {
+ let root = ReactDOM.Client.createRoot(container);
+ ReactDOM.Client.render(root, );
+ Js.Promise.resolve();
+ });
+
+ let valueElement = querySelector(".Value", container);
+ switch (valueElement) {
+ | Some(value) => expect(value->innerHTML)->toBe("0")
+ | None => failwith("Can't find 'Value' element")
+ };
+
+ let title = getTitle(document);
+ expect(title)->toBe("You clicked 0 times");
+
+ let.await () =
+ React.actAsync(() => {
+ let buttonElement = querySelector(".Increment", container);
+ switch (buttonElement) {
+ | Some(button) =>
+ dispatchEvent(button, mouseEvent("click", {"bubbles": true}))
+ | None => failwith("Can't find 'Increment' button")
+ };
+ Js.Promise.resolve();
+ });
+
+ let valueElement = querySelector(".Value", container);
+ switch (valueElement) {
+ | Some(value) => expect(value->innerHTML)->toBe("1")
+ | None => failwith("Can't find 'Value' element")
+ };
+
+ let title = getTitle(document);
+ expect(title)->toBe("You clicked 1 times");
+
+ finish();
});
- try(
- test("ErrorBoundary", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
+ test("ErrorBoundary + Suspense", () => {
+ [%mel.raw "console.error = () => {}"] |> ignore;
- act(() => {
- ReactDOM.Client.render(
- root,
+ try({
+ let container =
+ ReactTestingLibrary.render(
{
expect(
@@ -348,31 +381,23 @@ describe("React", () => {
->Js.String.includes(~search="ComponentThatThrows"),
)
->toBe(true);
- "An error occured"->React.string ;
+ "An error occured"->React.string ;
}}>
,
- )
- });
-
- expect(
- container
- ->DOM.findBySelectorAndTextContent("strong", "An error occured")
- ->Option.isSome,
- )
- ->toBe(true);
- })
- ) {
- | _error =>
- /* We catch the exception here to not populate the error to the toplevel */
- ()
- };
+ );
+
+ let error = getByRole("error", container);
+ expect(error->innerHTML)->toBe("An error occured");
+ }) {
+ | _error =>
+ /* We catch the exception here to not populate the error to the toplevel */
+ ()
+ };
+ });
test(
"Memo and normal components rendering with equal and different props", () => {
- let container = getContainer(container);
- let root = ReactDOM.Client.createRoot(container);
-
module Normal = {
let renders = ref(0);
@@ -394,27 +419,28 @@ describe("React", () => {
});
};
- act(() => {
- ReactDOM.Client.render(
- root,
+ let container =
+ ReactTestingLibrary.render(
,
- )
- });
- act(() => {
- ReactDOM.Client.render(
- root,
-
,
- )
- });
- act(() => {
- ReactDOM.Client.render(
- root,
-
,
- )
- });
+ );
- expect(Normal.renders^)->toBe(3);
+ expect(Normal.renders^)->toBe(1);
+ expect(Memo.renders^)->toBe(1);
+ ReactTestingLibrary.rerender(
+
,
+ container,
+ );
+
+ expect(Normal.renders^)->toBe(2);
+ expect(Memo.renders^)->toBe(1);
+
+ ReactTestingLibrary.rerender(
+
,
+ container,
+ );
+
+ expect(Normal.renders^)->toBe(3);
expect(Memo.renders^)->toBe(2);
});
});
diff --git a/test/dune b/test/dune
index a50a84e20..0dde05c81 100644
--- a/test/dune
+++ b/test/dune
@@ -3,6 +3,13 @@
(target test)
(module_systems
(commonjs bs.js))
- (libraries reason-react reason-react.node jest melange.belt)
+ (libraries
+ reason-react
+ reason-react.node
+ jest
+ melange.belt
+ melange.dom
+ melange_testing_library_dom
+ melange_testing_library_react)
(preprocess
(pps melange.ppx reason-react-ppx)))
diff --git a/test/jest/Jest.re b/test/jest/Jest.re
index 3c9a6bc5f..fa3a29742 100644
--- a/test/jest/Jest.re
+++ b/test/jest/Jest.re
@@ -22,6 +22,25 @@ let testAsync: (~timeout: int=?, string, (unit => unit) => unit) => unit =
(~timeout=?, name, f) =>
testAsyncU(name, callback => f(callback), timeout);
+external testPromiseU:
+ (
+ string,
+ (unit => Js.Promise.t(unit)) => Js.Promise.t(unit),
+ option(int)
+ ) =>
+ unit =
+ "test";
+
+let testPromise:
+ (
+ ~timeout: int=?,
+ string,
+ (unit => Js.Promise.t(unit)) => Js.Promise.t(unit)
+ ) =>
+ unit =
+ (~timeout=?, name, f) =>
+ testPromiseU(name, callback => f(callback), timeout);
+
module Only = {
[@mel.scope "describe"]
external describeU: (string, (. unit) => unit) => unit = "only";
diff --git a/test/melange-testing-library/README.md b/test/melange-testing-library/README.md
new file mode 100644
index 000000000..9711773d1
--- /dev/null
+++ b/test/melange-testing-library/README.md
@@ -0,0 +1,5 @@
+### vendored melange-testing-library
+
+This directory contains a vendored version of the melange-testing-library.
+
+The original repository is https://github.com/melange-community/melange-testing-library
diff --git a/test/melange-testing-library/dom/DomTestingLibrary.re b/test/melange-testing-library/dom/DomTestingLibrary.re
new file mode 100644
index 000000000..b2845661b
--- /dev/null
+++ b/test/melange-testing-library/dom/DomTestingLibrary.re
@@ -0,0 +1,4 @@
+include Queries;
+include Utils;
+
+module FireEvent = FireEvent;
diff --git a/test/melange-testing-library/dom/DomTestingLibrary.rei b/test/melange-testing-library/dom/DomTestingLibrary.rei
new file mode 100644
index 000000000..0ec173659
--- /dev/null
+++ b/test/melange-testing-library/dom/DomTestingLibrary.rei
@@ -0,0 +1,855 @@
+module FireEvent = FireEvent;
+
+module ByLabelTextQuery: {
+ type options = {
+ .
+ "selector": Js.undefined(string),
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~selector: string=?,
+ ~exact: bool=?,
+ ~normalizer: string => string=?,
+ unit
+ ) =>
+ options;
+};
+module ByPlaceholderTextQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByTextQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "selector": Js.undefined(string),
+ "ignore": Js.undefined(string),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~exact: bool=?,
+ ~selector: string=?,
+ ~ignore: string=?,
+ ~normalizer: string => string=?,
+ unit
+ ) =>
+ options;
+};
+module ByAltTextQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByTitleQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByDisplayValueQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByRoleQuery: {
+ type options = {
+ .
+ "checked": Js.undefined(bool),
+ "collapseWhitespace": Js.undefined(bool),
+ "exact": Js.undefined(bool),
+ "hidden": Js.undefined(bool),
+ "level": Js.undefined(int),
+ "pressed": Js.undefined(bool),
+ "name": Js.undefined(string),
+ "normalizer": Js.undefined(string => string),
+ "queryFallbacks": Js.undefined(bool),
+ "selected": Js.undefined(bool),
+ "trim": Js.undefined(bool),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~checked: bool=?,
+ ~collapseWhitespace: bool=?,
+ ~exact: bool=?,
+ ~hidden: bool=?,
+ ~level: int=?,
+ ~pressed: bool=?,
+ ~name: string=?,
+ ~normalizer: string => string=?,
+ ~queryFallbacks: bool=?,
+ ~selected: bool=?,
+ ~trim: bool=?,
+ unit
+ ) =>
+ options;
+};
+module ByTestIdQuery: {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module MutationObserver: {
+ type options = {
+ .
+ "attributeFilter": Js.undefined(array(string)),
+ "attributeOldValue": Js.undefined(bool),
+ "attributes": Js.undefined(bool),
+ "characterData": Js.undefined(bool),
+ "characterDataOldValue": Js.undefined(bool),
+ "childList": Js.undefined(bool),
+ "subtree": Js.undefined(bool),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~attributeFilter: array(string)=?,
+ ~attributeOldValue: bool=?,
+ ~attributes: bool=?,
+ ~characterData: bool=?,
+ ~characterDataOldValue: bool=?,
+ ~childList: bool=?,
+ ~subtree: bool=?,
+ unit
+ ) =>
+ options;
+};
+module WaitFor: {
+ type options = {
+ .
+ "container": Js.undefined(Dom.element),
+ "interval": Js.undefined(int),
+ "mutationObserverOptions": Js.undefined(MutationObserver.options),
+ "onTimeout": Js.undefined(Js.Exn.t => Js.Exn.t),
+ "showOriginalStackTrace": Js.undefined(bool),
+ "stackTraceError": Js.undefined(Js.Exn.t),
+ "timeout": Js.undefined(int),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~container: Dom.element=?,
+ ~interval: int=?,
+ ~mutationObserverOptions: MutationObserver.options=?,
+ ~onTimeout: Js.Exn.t => Js.Exn.t=?,
+ ~showOriginalStackTrace: bool=?,
+ ~stackTraceError: Js.Exn.t=?,
+ ~timeout: int=?,
+ unit
+ ) =>
+ options;
+};
+module WaitForElement: {
+ type options = {
+ .
+ "container": Js.undefined(Dom.element),
+ "timeout": Js.undefined(int),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~container: Dom.element=?,
+ ~mutationObserverInit: MutationObserver.options=?,
+ ~timeout: int=?,
+ unit
+ ) =>
+ options;
+};
+
+let waitFor: (~options: WaitFor.options=?, unit => unit) => Js.Promise.t('a);
+
+let waitForPromise:
+ (~options: WaitFor.options=?, unit => Js.Promise.t('a)) => Js.Promise.t('b);
+
+let waitForElement:
+ (~callback: unit => 'a=?, ~options: WaitForElement.options=?, unit) =>
+ Js.Promise.t('a);
+
+let waitForElementToBeRemoved:
+ (
+ ~callback: [
+ | `Func(unit => 'a)
+ | `Value('a)
+ ],
+ ~options: WaitFor.options=?,
+ unit
+ ) =>
+ Js.Promise.t(unit);
+
+let prettyDOM: (~maxLength: int=?, Dom.element) => string;
+
+let logDOM: (~maxLength: int=?, Dom.element) => unit;
+
+module Configure: {
+ type options = {
+ .
+ "_disableExpensiveErrorDiagnostics": Js.undefined(bool),
+ "asyncUtilTimeout": Js.undefined(int),
+ "asyncWrapper": Js.undefined(unit => unit),
+ "computedStyleSupportsPseudoElements": Js.undefined(bool),
+ "defaultHidden": Js.undefined(bool),
+ "eventWrapper": Js.undefined(unit => unit),
+ "getElementError": Js.undefined((string, Dom.element) => Js.Exn.t),
+ "showOriginalStackTrace": Js.undefined(bool),
+ "testIdAttribute": Js.undefined(string),
+ "throwSuggestions": Js.undefined(bool),
+ };
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~_disableExpensiveErrorDiagnostics: bool=?,
+ ~asyncUtilTimeout: int=?,
+ ~asyncWrapper: unit => unit=?,
+ ~computedStyleSupportsPseudoElements: bool=?,
+ ~defaultHidden: bool=?,
+ ~eventWrapper: unit => unit=?,
+ ~getElementError: (string, Dom.element) => Js.Exn.t=?,
+ ~showOriginalStackTrace: bool=?,
+ ~testIdAttribute: string=?,
+ ~throwSuggestions: bool=?,
+ unit
+ ) =>
+ options;
+};
+
+let configure:
+ (
+ ~update: [
+ | `Func(Configure.options => Configure.options)
+ | `Object(Configure.options)
+ ]
+ ) =>
+ unit;
+
+[@mel.module "@testing-library/dom"]
+external getNodeText: Dom.element => string = "getNodeText";
+
+/**
+ * ByLabelText
+ */
+let getByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByLabelTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByPlaceholderText
+ */
+let getByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByPlaceholderTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByText
+ */
+let getByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByAltText
+ */
+let getByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByAltTextQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByTitle
+ */
+let getByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByTitle:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTitleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByDisplayValue
+ */
+let getByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByDisplayValueQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByRole
+ */
+let getByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByRole:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByRoleQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+/**
+ * ByTestId
+ */
+let getByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ Dom.element;
+
+let getAllByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let queryByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ array(Dom.element);
+
+let findByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByTestId:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: ByTestIdQuery.options=?,
+ Dom.element
+ ) =>
+ Js.Promise.t(array(Dom.element));
diff --git a/test/melange-testing-library/dom/FireEvent.re b/test/melange-testing-library/dom/FireEvent.re
new file mode 100644
index 000000000..0fb3b560b
--- /dev/null
+++ b/test/melange-testing-library/dom/FireEvent.re
@@ -0,0 +1,404 @@
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _abort: (Dom.element, Js.undefined(Js.t({..}))) => unit = "abort";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _animationEnd: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "animationEnd";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _animationIteration: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "animationIteration";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _animationStart: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "animationStart";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _blur: (Dom.element, Js.undefined(Js.t({..}))) => unit = "blur";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _canPlay: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "canPlay";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _canPlayThrough: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "canPlayThrough";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _change: (Dom.element, Js.undefined(Js.t({..}))) => unit = "change";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _click: (Dom.element, Js.undefined(Js.t({..}))) => unit = "click";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _compositionEnd: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "compositionEnd";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _compositionStart: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "compositionStart";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _compositionUpdate: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "compositionUpdate";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _contextMenu: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "contextMenu";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _copy: (Dom.element, Js.undefined(Js.t({..}))) => unit = "copy";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _cut: (Dom.element, Js.undefined(Js.t({..}))) => unit = "cut";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dblClick: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dblClick";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _doubleClick: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "doubleClick";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _drag: (Dom.element, Js.undefined(Js.t({..}))) => unit = "drag";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragEnd: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragEnd";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragEnter: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragEnter";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragExit: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragExit";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragLeave: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragLeave";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragOver: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragOver";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _dragStart: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "dragStart";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _drop: (Dom.element, Js.undefined(Js.t({..}))) => unit = "drop";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _durationChange: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "durationChange";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _emptied: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "emptied";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _encrypted: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "encrypted";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _ended: (Dom.element, Js.undefined(Js.t({..}))) => unit = "ended";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _error: (Dom.element, Js.undefined(Js.t({..}))) => unit = "error";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _focus: (Dom.element, Js.undefined(Js.t({..}))) => unit = "focus";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _focusIn: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "focusIn";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _focusOut: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "focusOut";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _input: (Dom.element, Js.undefined(Js.t({..}))) => unit = "input";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _invalid: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "invalid";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _keyDown: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "keyDown";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _keyPress: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "keyPress";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _keyUp: (Dom.element, Js.undefined(Js.t({..}))) => unit = "keyUp";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _load: (Dom.element, Js.undefined(Js.t({..}))) => unit = "load";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _loadStart: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "loadStart";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _loadedData: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "loadedData";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _loadedMetadata: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "loadedMetadata";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseDown: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseDown";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseEnter: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseEnter";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseLeave: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseLeave";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseMove: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseMove";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseOut: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseOut";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseOver: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseOver";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _mouseUp: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "mouseUp";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _paste: (Dom.element, Js.undefined(Js.t({..}))) => unit = "paste";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _pause: (Dom.element, Js.undefined(Js.t({..}))) => unit = "pause";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _play: (Dom.element, Js.undefined(Js.t({..}))) => unit = "play";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _playing: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "playing";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _progress: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "progress";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _rateChange: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "rateChange";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _scroll: (Dom.element, Js.undefined(Js.t({..}))) => unit = "scroll";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _seeked: (Dom.element, Js.undefined(Js.t({..}))) => unit = "seeked";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _seeking: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "seeking";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _select: (Dom.element, Js.undefined(Js.t({..}))) => unit = "select";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _stalled: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "stalled";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _submit: (Dom.element, Js.undefined(Js.t({..}))) => unit = "submit";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _suspend: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "suspend";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _timeUpdate: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "timeUpdate";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _touchCancel: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "touchCancel";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _touchEnd: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "touchEnd";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _touchMove: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "touchMove";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _touchStart: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "touchStart";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _transitionEnd: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "transitionEnd";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _volumeChange: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "volumeChange";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _waiting: (Dom.element, Js.undefined(Js.t({..}))) => unit =
+ "waiting";
+
+[@mel.module "@testing-library/dom"] [@mel.scope "fireEvent"]
+external _wheel: (Dom.element, Js.undefined(Js.t({..}))) => unit = "wheel";
+
+let abort = (~eventInit=?, el) =>
+ _abort(el, Js.Undefined.fromOption(eventInit));
+let animationEnd = (~eventInit=?, el) =>
+ _animationEnd(el, Js.Undefined.fromOption(eventInit));
+let animationIteration = (~eventInit=?, el) =>
+ _animationIteration(el, Js.Undefined.fromOption(eventInit));
+let animationStart = (~eventInit=?, el) =>
+ _animationStart(el, Js.Undefined.fromOption(eventInit));
+let blur = (~eventInit=?, el) =>
+ _blur(el, Js.Undefined.fromOption(eventInit));
+let canPlay = (~eventInit=?, el) =>
+ _canPlay(el, Js.Undefined.fromOption(eventInit));
+let canPlayThrough = (~eventInit=?, el) =>
+ _canPlayThrough(el, Js.Undefined.fromOption(eventInit));
+let change = (~eventInit=?, el) =>
+ _change(el, Js.Undefined.fromOption(eventInit));
+let click = (~eventInit=?, el) =>
+ _click(el, Js.Undefined.fromOption(eventInit));
+let compositionEnd = (~eventInit=?, el) =>
+ _compositionEnd(el, Js.Undefined.fromOption(eventInit));
+let compositionStart = (~eventInit=?, el) =>
+ _compositionStart(el, Js.Undefined.fromOption(eventInit));
+let compositionUpdate = (~eventInit=?, el) =>
+ _compositionUpdate(el, Js.Undefined.fromOption(eventInit));
+let contextMenu = (~eventInit=?, el) =>
+ _contextMenu(el, Js.Undefined.fromOption(eventInit));
+let copy = (~eventInit=?, el) =>
+ _copy(el, Js.Undefined.fromOption(eventInit));
+let cut = (~eventInit=?, el) =>
+ _cut(el, Js.Undefined.fromOption(eventInit));
+let dblClick = (~eventInit=?, el) =>
+ _dblClick(el, Js.Undefined.fromOption(eventInit));
+let doubleClick = (~eventInit=?, el) =>
+ _doubleClick(el, Js.Undefined.fromOption(eventInit));
+let drag = (~eventInit=?, el) =>
+ _drag(el, Js.Undefined.fromOption(eventInit));
+let dragEnd = (~eventInit=?, el) =>
+ _dragEnd(el, Js.Undefined.fromOption(eventInit));
+let dragEnter = (~eventInit=?, el) =>
+ _dragEnter(el, Js.Undefined.fromOption(eventInit));
+let dragExit = (~eventInit=?, el) =>
+ _dragExit(el, Js.Undefined.fromOption(eventInit));
+let dragLeave = (~eventInit=?, el) =>
+ _dragLeave(el, Js.Undefined.fromOption(eventInit));
+let dragOver = (~eventInit=?, el) =>
+ _dragOver(el, Js.Undefined.fromOption(eventInit));
+let dragStart = (~eventInit=?, el) =>
+ _dragStart(el, Js.Undefined.fromOption(eventInit));
+let drop = (~eventInit=?, el) =>
+ _drop(el, Js.Undefined.fromOption(eventInit));
+let durationChange = (~eventInit=?, el) =>
+ _durationChange(el, Js.Undefined.fromOption(eventInit));
+let emptied = (~eventInit=?, el) =>
+ _emptied(el, Js.Undefined.fromOption(eventInit));
+let encrypted = (~eventInit=?, el) =>
+ _encrypted(el, Js.Undefined.fromOption(eventInit));
+let ended = (~eventInit=?, el) =>
+ _ended(el, Js.Undefined.fromOption(eventInit));
+let error = (~eventInit=?, el) =>
+ _error(el, Js.Undefined.fromOption(eventInit));
+let focus = (~eventInit=?, el) =>
+ _focus(el, Js.Undefined.fromOption(eventInit));
+let focusIn = (~eventInit=?, el) =>
+ _focusIn(el, Js.Undefined.fromOption(eventInit));
+let focusOut = (~eventInit=?, el) =>
+ _focusOut(el, Js.Undefined.fromOption(eventInit));
+let input = (~eventInit=?, el) =>
+ _input(el, Js.Undefined.fromOption(eventInit));
+let invalid = (~eventInit=?, el) =>
+ _invalid(el, Js.Undefined.fromOption(eventInit));
+let keyDown = (~eventInit=?, el) =>
+ _keyDown(el, Js.Undefined.fromOption(eventInit));
+let keyPress = (~eventInit=?, el) =>
+ _keyPress(el, Js.Undefined.fromOption(eventInit));
+let keyUp = (~eventInit=?, el) =>
+ _keyUp(el, Js.Undefined.fromOption(eventInit));
+let load = (~eventInit=?, el) =>
+ _load(el, Js.Undefined.fromOption(eventInit));
+let loadStart = (~eventInit=?, el) =>
+ _loadStart(el, Js.Undefined.fromOption(eventInit));
+let loadedData = (~eventInit=?, el) =>
+ _loadedData(el, Js.Undefined.fromOption(eventInit));
+let loadedMetadata = (~eventInit=?, el) =>
+ _loadedMetadata(el, Js.Undefined.fromOption(eventInit));
+let mouseDown = (~eventInit=?, el) =>
+ _mouseDown(el, Js.Undefined.fromOption(eventInit));
+let mouseEnter = (~eventInit=?, el) =>
+ _mouseEnter(el, Js.Undefined.fromOption(eventInit));
+let mouseLeave = (~eventInit=?, el) =>
+ _mouseLeave(el, Js.Undefined.fromOption(eventInit));
+let mouseMove = (~eventInit=?, el) =>
+ _mouseMove(el, Js.Undefined.fromOption(eventInit));
+let mouseOut = (~eventInit=?, el) =>
+ _mouseOut(el, Js.Undefined.fromOption(eventInit));
+let mouseOver = (~eventInit=?, el) =>
+ _mouseOver(el, Js.Undefined.fromOption(eventInit));
+let mouseUp = (~eventInit=?, el) =>
+ _mouseUp(el, Js.Undefined.fromOption(eventInit));
+let paste = (~eventInit=?, el) =>
+ _paste(el, Js.Undefined.fromOption(eventInit));
+let pause = (~eventInit=?, el) =>
+ _pause(el, Js.Undefined.fromOption(eventInit));
+let play = (~eventInit=?, el) =>
+ _play(el, Js.Undefined.fromOption(eventInit));
+let playing = (~eventInit=?, el) =>
+ _playing(el, Js.Undefined.fromOption(eventInit));
+let progress = (~eventInit=?, el) =>
+ _progress(el, Js.Undefined.fromOption(eventInit));
+let rateChange = (~eventInit=?, el) =>
+ _rateChange(el, Js.Undefined.fromOption(eventInit));
+let scroll = (~eventInit=?, el) =>
+ _scroll(el, Js.Undefined.fromOption(eventInit));
+let seeked = (~eventInit=?, el) =>
+ _seeked(el, Js.Undefined.fromOption(eventInit));
+let seeking = (~eventInit=?, el) =>
+ _seeking(el, Js.Undefined.fromOption(eventInit));
+let select = (~eventInit=?, el) =>
+ _select(el, Js.Undefined.fromOption(eventInit));
+let stalled = (~eventInit=?, el) =>
+ _stalled(el, Js.Undefined.fromOption(eventInit));
+let submit = (~eventInit=?, el) =>
+ _submit(el, Js.Undefined.fromOption(eventInit));
+let suspend = (~eventInit=?, el) =>
+ _suspend(el, Js.Undefined.fromOption(eventInit));
+let timeUpdate = (~eventInit=?, el) =>
+ _timeUpdate(el, Js.Undefined.fromOption(eventInit));
+let touchCancel = (~eventInit=?, el) =>
+ _touchCancel(el, Js.Undefined.fromOption(eventInit));
+let touchEnd = (~eventInit=?, el) =>
+ _touchEnd(el, Js.Undefined.fromOption(eventInit));
+let touchMove = (~eventInit=?, el) =>
+ _touchMove(el, Js.Undefined.fromOption(eventInit));
+let touchStart = (~eventInit=?, el) =>
+ _touchStart(el, Js.Undefined.fromOption(eventInit));
+let transitionEnd = (~eventInit=?, el) =>
+ _transitionEnd(el, Js.Undefined.fromOption(eventInit));
+let volumeChange = (~eventInit=?, el) =>
+ _volumeChange(el, Js.Undefined.fromOption(eventInit));
+let waiting = (~eventInit=?, el) =>
+ _waiting(el, Js.Undefined.fromOption(eventInit));
+let wheel = (~eventInit=?, el) =>
+ _wheel(el, Js.Undefined.fromOption(eventInit));
diff --git a/test/melange-testing-library/dom/FireEvent.rei b/test/melange-testing-library/dom/FireEvent.rei
new file mode 100644
index 000000000..1c791995b
--- /dev/null
+++ b/test/melange-testing-library/dom/FireEvent.rei
@@ -0,0 +1,71 @@
+let abort: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let animationEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let animationIteration: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let animationStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let blur: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let canPlay: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let canPlayThrough: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let change: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let click: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let compositionEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let compositionStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let compositionUpdate: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let contextMenu: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let copy: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let cut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dblClick: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let doubleClick: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let drag: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragEnter: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragExit: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragLeave: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragOver: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let dragStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let drop: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let durationChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let emptied: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let encrypted: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let ended: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let error: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let focus: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let focusIn: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let focusOut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let input: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let invalid: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let keyDown: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let keyPress: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let keyUp: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let load: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let loadStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let loadedData: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let loadedMetadata: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseDown: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseEnter: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseLeave: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseMove: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseOut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseOver: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let mouseUp: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let paste: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let pause: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let play: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let playing: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let progress: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let rateChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let scroll: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let seeked: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let seeking: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let select: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let stalled: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let submit: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let suspend: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let timeUpdate: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let touchCancel: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let touchEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let touchMove: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let touchStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let transitionEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let volumeChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let waiting: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+let wheel: (~eventInit: Js.t({..})=?, Dom.element) => unit;
diff --git a/test/melange-testing-library/dom/Queries.re b/test/melange-testing-library/dom/Queries.re
new file mode 100644
index 000000000..0c05fd206
--- /dev/null
+++ b/test/melange-testing-library/dom/Queries.re
@@ -0,0 +1,1126 @@
+module ByLabelTextQuery = {
+ type options = {
+ .
+ "selector": Js.undefined(string),
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~selector: string=?,
+ ~exact: bool=?,
+ ~normalizer: string => string=?,
+ unit
+ ) =>
+ options;
+};
+module ByPlaceholderTextQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByTextQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "selector": Js.undefined(string),
+ "ignore": Js.undefined(string),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~exact: bool=?,
+ ~selector: string=?,
+ ~ignore: string=?,
+ ~normalizer: string => string=?,
+ unit
+ ) =>
+ options;
+};
+module ByAltTextQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByTitleQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByDisplayValueQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+module ByRoleQuery = {
+ type options = {
+ .
+ "checked": Js.undefined(bool),
+ "collapseWhitespace": Js.undefined(bool),
+ "exact": Js.undefined(bool),
+ "hidden": Js.undefined(bool),
+ "level": Js.undefined(int),
+ "pressed": Js.undefined(bool),
+ "name": Js.undefined(string),
+ "normalizer": Js.undefined(string => string),
+ "queryFallbacks": Js.undefined(bool),
+ "selected": Js.undefined(bool),
+ "trim": Js.undefined(bool),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~checked: bool=?,
+ ~collapseWhitespace: bool=?,
+ ~exact: bool=?,
+ ~hidden: bool=?,
+ ~level: int=?,
+ ~pressed: bool=?,
+ ~name: string=?,
+ ~normalizer: string => string=?,
+ ~queryFallbacks: bool=?,
+ ~selected: bool=?,
+ ~trim: bool=?,
+ unit
+ ) =>
+ options;
+};
+module ByTestIdQuery = {
+ type options = {
+ .
+ "exact": Js.undefined(bool),
+ "normalizer": Js.undefined(string => string),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (~exact: bool=?, ~normalizer: string => string=?, unit) => options;
+};
+
+[@mel.module "@testing-library/dom"]
+external getNodeText: Dom.element => string = "getNodeText";
+
+/**
+ * ByLabelText
+ */
+[@mel.module "@testing-library/dom"]
+external _getByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByLabelText";
+
+let getByLabelText = (~matcher, ~options=?, element) =>
+ _getByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _getAllByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByLabelText";
+
+let getAllByLabelText = (~matcher, ~options=?, element) =>
+ _getAllByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByLabelText";
+
+let queryByLabelText = (~matcher, ~options=?, element) =>
+ _queryByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByLabelText";
+
+let queryAllByLabelText = (~matcher, ~options=?, element) =>
+ _queryAllByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByLabelText";
+
+let findByLabelText = (~matcher, ~options=?, element) =>
+ _findByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findAllByLabelText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByLabelText";
+
+let findAllByLabelText = (~matcher, ~options=?, element) =>
+ _findAllByLabelText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByPlaceholderText
+ */
+[@mel.module "@testing-library/dom"]
+external _getByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByPlaceholderText";
+
+let getByPlaceholderText = (~matcher, ~options=?, element) =>
+ _getByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _getAllByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByPlaceholderText";
+
+let getAllByPlaceholderText = (~matcher, ~options=?, element) =>
+ _getAllByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByPlaceholderText";
+
+let queryByPlaceholderText = (~matcher, ~options=?, element) =>
+ _queryByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByPlaceholderText";
+
+let queryAllByPlaceholderText = (~matcher, ~options=?, element) =>
+ _queryAllByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByPlaceholderText";
+
+let findByPlaceholderText = (~matcher, ~options=?, element) =>
+ _findByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findAllByPlaceholderText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByPlaceholderText";
+
+let findAllByPlaceholderText = (~matcher, ~options=?, element) =>
+ _findAllByPlaceholderText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByText
+ */
+[@mel.module "@testing-library/dom"]
+external _getByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByText";
+
+let getByText = (~matcher, ~options=?, element) =>
+ _getByText(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _getAllByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByText";
+
+let getAllByText = (~matcher, ~options=?, element) =>
+ _getAllByText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByText";
+
+let queryByText = (~matcher, ~options=?, element) =>
+ _queryByText(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByText";
+
+let queryAllByText = (~matcher, ~options=?, element) =>
+ _queryAllByText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByText";
+
+let findByText = (~matcher, ~options=?, element) =>
+ _findByText(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _findAllByText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByText";
+
+let findAllByText = (~matcher, ~options=?, element) =>
+ _findAllByText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByAltText
+ */
+[@mel.module "@testing-library/dom"]
+external _getByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByAltText";
+
+let getByAltText = (~matcher, ~options=?, element) =>
+ _getByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _getAllByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByAltText";
+
+let getAllByAltText = (~matcher, ~options=?, element) =>
+ _getAllByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByAltText";
+
+let queryByAltText = (~matcher, ~options=?, element) =>
+ _queryByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByAltText";
+
+let queryAllByAltText = (~matcher, ~options=?, element) =>
+ _queryAllByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByAltText";
+
+let findByAltText = (~matcher, ~options=?, element) =>
+ _findByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findAllByAltText:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByAltText";
+
+let findAllByAltText = (~matcher, ~options=?, element) =>
+ _findAllByAltText(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByTitle
+ */
+[@mel.module "@testing-library/dom"]
+external _getByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Dom.element =
+ "getByTitle";
+
+let getByTitle = (~matcher, ~options=?, element) =>
+ _getByTitle(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _getAllByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByTitle";
+
+let getAllByTitle = (~matcher, ~options=?, element) =>
+ _getAllByTitle(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByTitle";
+
+let queryByTitle = (~matcher, ~options=?, element) =>
+ _queryByTitle(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByTitle";
+
+let queryAllByTitle = (~matcher, ~options=?, element) =>
+ _queryAllByTitle(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByTitle";
+
+let findByTitle = (~matcher, ~options=?, element) =>
+ _findByTitle(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _findAllByTitle:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByTitle";
+
+let findAllByTitle = (~matcher, ~options=?, element) =>
+ _findAllByTitle(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByDisplayValue
+ */
+[@mel.module "@testing-library/dom"]
+external _getByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Dom.element =
+ "getByDisplayValue";
+
+let getByDisplayValue = (~matcher, ~options=?, element) =>
+ _getByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _getAllByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByDisplayValue";
+
+let getAllByDisplayValue = (~matcher, ~options=?, element) =>
+ _getAllByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByDisplayValue";
+
+let queryByDisplayValue = (~matcher, ~options=?, element) =>
+ _queryByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByDisplayValue";
+
+let queryAllByDisplayValue = (~matcher, ~options=?, element) =>
+ _queryAllByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByDisplayValue";
+
+let findByDisplayValue = (~matcher, ~options=?, element) =>
+ _findByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findAllByDisplayValue:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByDisplayValue";
+
+let findAllByDisplayValue = (~matcher, ~options=?, element) =>
+ _findAllByDisplayValue(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByRole
+ */
+[@mel.module "@testing-library/dom"]
+external _getByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Dom.element =
+ "getByRole";
+
+let getByRole = (~matcher, ~options=?, element) =>
+ _getByRole(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _getAllByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByRole";
+
+let getAllByRole = (~matcher, ~options=?, element) =>
+ _getAllByRole(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByRole";
+
+let queryByRole = (~matcher, ~options=?, element) =>
+ _queryByRole(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByRole";
+
+let queryAllByRole = (~matcher, ~options=?, element) =>
+ _queryAllByRole(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByRole";
+
+let findByRole = (~matcher, ~options=?, element) =>
+ _findByRole(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _findAllByRole:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByRole";
+
+let findAllByRole = (~matcher, ~options=?, element) =>
+ _findAllByRole(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+/**
+ * ByTestId
+ */
+[@mel.module "@testing-library/dom"]
+external _getByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Dom.element =
+ "getByTestId";
+
+let getByTestId = (~matcher, ~options=?, element) =>
+ _getByTestId(element, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _getAllByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByTestId";
+
+let getAllByTestId = (~matcher, ~options=?, element) =>
+ _getAllByTestId(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByTestId";
+
+let queryByTestId = (~matcher, ~options=?, element) =>
+ _queryByTestId(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _queryAllByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByTestId";
+
+let queryAllByTestId = (~matcher, ~options=?, element) =>
+ _queryAllByTestId(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByTestId";
+
+let findByTestId = (~matcher, ~options=?, element) =>
+ _findByTestId(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _findAllByTestId:
+ (
+ Dom.element,
+ ~matcher: [@mel.unwrap] [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByTestId";
+
+let findAllByTestId = (~matcher, ~options=?, element) =>
+ _findAllByTestId(
+ element,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
diff --git a/test/melange-testing-library/dom/Utils.re b/test/melange-testing-library/dom/Utils.re
new file mode 100644
index 000000000..b4de999ed
--- /dev/null
+++ b/test/melange-testing-library/dom/Utils.re
@@ -0,0 +1,180 @@
+module MutationObserver = {
+ type options = {
+ .
+ "attributeFilter": Js.undefined(array(string)),
+ "attributeOldValue": Js.undefined(bool),
+ "attributes": Js.undefined(bool),
+ "characterData": Js.undefined(bool),
+ "characterDataOldValue": Js.undefined(bool),
+ "childList": Js.undefined(bool),
+ "subtree": Js.undefined(bool),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~attributeFilter: array(string)=?,
+ ~attributeOldValue: bool=?,
+ ~attributes: bool=?,
+ ~characterData: bool=?,
+ ~characterDataOldValue: bool=?,
+ ~childList: bool=?,
+ ~subtree: bool=?,
+ unit
+ ) =>
+ options;
+};
+
+module WaitFor = {
+ type options = {
+ .
+ "container": Js.undefined(Dom.element),
+ "interval": Js.undefined(int),
+ "mutationObserverOptions": Js.undefined(MutationObserver.options),
+ "onTimeout": Js.undefined(Js.Exn.t => Js.Exn.t),
+ "showOriginalStackTrace": Js.undefined(bool),
+ "stackTraceError": Js.undefined(Js.Exn.t),
+ "timeout": Js.undefined(int),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~container: Dom.element=?,
+ ~interval: int=?,
+ ~mutationObserverOptions: MutationObserver.options=?,
+ ~onTimeout: Js.Exn.t => Js.Exn.t=?,
+ ~showOriginalStackTrace: bool=?,
+ ~stackTraceError: Js.Exn.t=?,
+ ~timeout: int=?,
+ unit
+ ) =>
+ options;
+};
+
+module WaitForElement = {
+ type options = {
+ .
+ "container": Js.undefined(Dom.element),
+ "timeout": Js.undefined(int),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~container: Dom.element=?,
+ ~mutationObserverInit: MutationObserver.options=?,
+ ~timeout: int=?,
+ unit
+ ) =>
+ options;
+};
+
+[@mel.module "@testing-library/dom"]
+external _waitFor:
+ (unit => unit, Js.undefined(WaitFor.options)) => Js.Promise.t('a) =
+ "waitFor";
+
+let waitFor = (~options=?, callback) =>
+ _waitFor(callback, Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _waitForPromise:
+ (unit => Js.Promise.t('a), Js.undefined(WaitFor.options)) =>
+ Js.Promise.t('b) =
+ "waitFor";
+
+let waitForPromise = (~options=?, callback) =>
+ _waitForPromise(callback, Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _waitForElement:
+ (Js.undefined(unit => 'a), Js.undefined(WaitForElement.options)) =>
+ Js.Promise.t('a) =
+ "waitForElement";
+
+let waitForElement = (~callback=?, ~options=?, ()) =>
+ _waitForElement(
+ Js.Undefined.fromOption(callback),
+ Js.Undefined.fromOption(options),
+ );
+
+[@mel.module "@testing-library/dom"]
+external _waitForElementToBeRemoved:
+ (
+ ~callback:
+ [@mel.unwrap] [
+ | `Func(unit => 'a)
+ | `Value('a)
+ ],
+ Js.undefined(WaitFor.options)
+ ) =>
+ Js.Promise.t(unit) =
+ "waitForElementToBeRemoved";
+
+let waitForElementToBeRemoved = (~callback, ~options=?, ()) =>
+ _waitForElementToBeRemoved(~callback, Js.Undefined.fromOption(options));
+
+[@mel.module "@testing-library/dom"]
+external _prettyDOM: (Dom.element, Js.undefined(int)) => string = "prettyDOM";
+
+let prettyDOM = (~maxLength=?, element) =>
+ _prettyDOM(element, Js.Undefined.fromOption(maxLength));
+
+[@mel.module "@testing-library/dom"]
+external _logDOM: (Dom.element, Js.undefined(int)) => unit = "logDOM";
+
+let logDOM = (~maxLength=?, element) =>
+ _logDOM(element, Js.Undefined.fromOption(maxLength));
+
+module Configure = {
+ type options = {
+ .
+ "_disableExpensiveErrorDiagnostics": Js.undefined(bool),
+ "asyncUtilTimeout": Js.undefined(int),
+ "asyncWrapper": Js.undefined(unit => unit),
+ "computedStyleSupportsPseudoElements": Js.undefined(bool),
+ "defaultHidden": Js.undefined(bool),
+ "eventWrapper": Js.undefined(unit => unit),
+ "getElementError": Js.undefined((string, Dom.element) => Js.Exn.t),
+ "showOriginalStackTrace": Js.undefined(bool),
+ "testIdAttribute": Js.undefined(string),
+ "throwSuggestions": Js.undefined(bool),
+ };
+
+ [@mel.obj]
+ external makeOptions:
+ (
+ ~_disableExpensiveErrorDiagnostics: bool=?,
+ ~asyncUtilTimeout: int=?,
+ ~asyncWrapper: unit => unit=?,
+ ~computedStyleSupportsPseudoElements: bool=?,
+ ~defaultHidden: bool=?,
+ ~eventWrapper: unit => unit=?,
+ ~getElementError: (string, Dom.element) => Js.Exn.t=?,
+ ~showOriginalStackTrace: bool=?,
+ ~testIdAttribute: string=?,
+ ~throwSuggestions: bool=?,
+ unit
+ ) =>
+ options;
+};
+
+[@mel.module "@testing-library/dom"]
+external configureWithFn: (Js.t({..}) => Js.t({..})) => unit = "configure";
+
+[@mel.module "@testing-library/dom"]
+external configureWithObject: Configure.options => unit = "configure";
+
+let configure =
+ (
+ ~update: [
+ | `Func(Configure.options => Configure.options)
+ | `Object(Configure.options)
+ ],
+ ) => {
+ switch (update) {
+ | `Func(fn) => configureWithFn(fn)
+ | `Object(obj) => configureWithObject(obj)
+ };
+};
diff --git a/test/melange-testing-library/dom/dune b/test/melange-testing-library/dom/dune
new file mode 100644
index 000000000..8ae145e24
--- /dev/null
+++ b/test/melange-testing-library/dom/dune
@@ -0,0 +1,7 @@
+(library
+ (name melange_testing_library_dom)
+ (wrapped false)
+ (modes melange)
+ (libraries melange.dom)
+ (preprocess
+ (pps melange.ppx)))
diff --git a/test/melange-testing-library/react/ReactTestingLibrary.re b/test/melange-testing-library/react/ReactTestingLibrary.re
new file mode 100644
index 000000000..879157830
--- /dev/null
+++ b/test/melange-testing-library/react/ReactTestingLibrary.re
@@ -0,0 +1,1044 @@
+open DomTestingLibrary;
+
+module FireEvent = FireEvent;
+
+type renderResult;
+type queries;
+type renderOptions = {
+ .
+ "container": Js.undefined(Dom.element),
+ "baseElement": Js.undefined(Dom.element),
+ "hydrate": Js.undefined(bool),
+ "wrapper": Js.undefined(Dom.element),
+ "queries": Js.undefined(queries),
+};
+
+[@mel.module "@testing-library/react"]
+external cleanup: unit => unit = "cleanup";
+
+[@mel.module "@testing-library/react"]
+external actAsync: (unit => Js.Promise.t('a)) => Js.Promise.t(unit) = "act";
+
+[@mel.module "@testing-library/react"]
+external _act: (unit => Js.undefined(Js.Promise.t('a))) => unit = "act";
+
+let act = callback =>
+ _act(() => {
+ callback();
+ // (work-around) BuckleScript compiles `unit` to `0`, this will cause a warning as following:
+ // Warning: The callback passed to act(...) function must return undefined, or a Promise.
+ Js.Undefined.empty;
+ });
+
+[@mel.module "@testing-library/react"]
+external _render: (React.element, renderOptions) => renderResult = "render";
+
+[@mel.get] external container: renderResult => Dom.element = "container";
+
+[@mel.get] external baseElement: renderResult => Dom.element = "baseElement";
+
+[@mel.send.pipe: renderResult]
+external _debug: (Js.undefined(Dom.element), Js.undefined(int)) => unit =
+ "debug";
+
+[@mel.send.pipe: renderResult] external unmount: unit => bool = "unmount";
+
+[@mel.send.pipe: renderResult]
+external rerender: React.element => unit = "rerender";
+
+[@mel.send.pipe: renderResult]
+external asFragment: unit => Dom.element = "asFragment";
+
+// ByLabelText
+[@mel.send.pipe: renderResult]
+external _getByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByLabelText";
+
+let getByLabelText = (~matcher, ~options=?, result) =>
+ _getByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _getAllByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByLabelText";
+
+let getAllByLabelText = (~matcher, ~options=?, result) =>
+ _getAllByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByLabelText";
+
+let queryByLabelText = (~matcher, ~options=?, result) =>
+ _queryByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryAllByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByLabelText";
+
+let queryAllByLabelText = (~matcher, ~options=?, result) =>
+ _queryAllByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByLabelText";
+
+let findByLabelText = (~matcher, ~options=?, result) =>
+ _findByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findAllByLabelText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByLabelTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByLabelText";
+
+let findAllByLabelText = (~matcher, ~options=?, result) =>
+ _findAllByLabelText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByPlaceholderText
+[@mel.send.pipe: renderResult]
+external _getByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByPlaceholderText";
+
+let getByPlaceholderText = (~matcher, ~options=?, result) =>
+ _getByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _getAllByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByPlaceholderText";
+
+let getAllByPlaceholderText = (~matcher, ~options=?, result) =>
+ _getAllByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByPlaceholderText";
+
+let queryByPlaceholderText = (~matcher, ~options=?, result) =>
+ _queryByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryAllByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByPlaceholderText";
+
+let queryAllByPlaceholderText = (~matcher, ~options=?, result) =>
+ _queryAllByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByPlaceholderText";
+
+let findByPlaceholderText = (~matcher, ~options=?, result) =>
+ _findByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findAllByPlaceholderText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByPlaceholderTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByPlaceholderText";
+
+let findAllByPlaceholderText = (~matcher, ~options=?, result) =>
+ _findAllByPlaceholderText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByText
+[@mel.send.pipe: renderResult]
+external _getByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByText";
+
+let getByText = (~matcher, ~options=?, result) =>
+ _getByText(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _getAllByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByText";
+
+let getAllByText = (~matcher, ~options=?, result) =>
+ _getAllByText(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _queryByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByText";
+
+let queryByText = (~matcher, ~options=?, result) =>
+ _queryByText(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _queryAllByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByText";
+
+let queryAllByText = (~matcher, ~options=?, result) =>
+ _queryAllByText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByText";
+
+let findByText = (~matcher, ~options=?, result) =>
+ _findByText(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _findAllByText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByText";
+
+let findAllByText = (~matcher, ~options=?, result) =>
+ _findAllByText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByAltText
+[@mel.send.pipe: renderResult]
+external _getByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Dom.element =
+ "getByAltText";
+
+let getByAltText = (~matcher, ~options=?, result) =>
+ _getByAltText(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _getAllByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByAltText";
+
+let getAllByAltText = (~matcher, ~options=?, result) =>
+ _getAllByAltText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByAltText";
+
+let queryByAltText = (~matcher, ~options=?, result) =>
+ _queryByAltText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryAllByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByAltText";
+
+let queryAllByAltText = (~matcher, ~options=?, result) =>
+ _queryAllByAltText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByAltText";
+
+let findByAltText = (~matcher, ~options=?, result) =>
+ _findByAltText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findAllByAltText:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByAltTextQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByAltText";
+
+let findAllByAltText = (~matcher, ~options=?, result) =>
+ _findAllByAltText(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByTitle
+[@mel.send.pipe: renderResult]
+external _getByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Dom.element =
+ "getByTitle";
+
+let getByTitle = (~matcher, ~options=?, result) =>
+ _getByTitle(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _getAllByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByTitle";
+
+let getAllByTitle = (~matcher, ~options=?, result) =>
+ _getAllByTitle(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByTitle";
+
+let queryByTitle = (~matcher, ~options=?, result) =>
+ _queryByTitle(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _queryAllByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByTitle";
+
+let queryAllByTitle = (~matcher, ~options=?, result) =>
+ _queryAllByTitle(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByTitle";
+
+let findByTitle = (~matcher, ~options=?, result) =>
+ _findByTitle(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _findAllByTitle:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTitleQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByTitle";
+
+let findAllByTitle = (~matcher, ~options=?, result) =>
+ _findAllByTitle(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByDisplayValue
+[@mel.send.pipe: renderResult]
+external _getByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Dom.element =
+ "getByDisplayValue";
+
+let getByDisplayValue = (~matcher, ~options=?, result) =>
+ _getByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _getAllByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByDisplayValue";
+
+let getAllByDisplayValue = (~matcher, ~options=?, result) =>
+ _getAllByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByDisplayValue";
+
+let queryByDisplayValue = (~matcher, ~options=?, result) =>
+ _queryByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryAllByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByDisplayValue";
+
+let queryAllByDisplayValue = (~matcher, ~options=?, result) =>
+ _queryAllByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByDisplayValue";
+
+let findByDisplayValue = (~matcher, ~options=?, result) =>
+ _findByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findAllByDisplayValue:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByDisplayValueQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByDisplayValue";
+
+let findAllByDisplayValue = (~matcher, ~options=?, result) =>
+ _findAllByDisplayValue(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByRole
+[@mel.send.pipe: renderResult]
+external _getByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Dom.element =
+ "getByRole";
+
+let getByRole = (~matcher, ~options=?, result) =>
+ _getByRole(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _getAllByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByRole";
+
+let getAllByRole = (~matcher, ~options=?, result) =>
+ _getAllByRole(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _queryByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByRole";
+
+let queryByRole = (~matcher, ~options=?, result) =>
+ _queryByRole(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _queryAllByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByRole";
+
+let queryAllByRole = (~matcher, ~options=?, result) =>
+ _queryAllByRole(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByRole";
+
+let findByRole = (~matcher, ~options=?, result) =>
+ _findByRole(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _findAllByRole:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByRoleQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByRole";
+
+let findAllByRole = (~matcher, ~options=?, result) =>
+ _findAllByRole(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+// ByTestId
+[@mel.send.pipe: renderResult]
+external _getByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Dom.element =
+ "getByTestId";
+
+let getByTestId = (~matcher, ~options=?, result) =>
+ _getByTestId(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _getAllByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ array(Dom.element) =
+ "getAllByTestId";
+
+let getAllByTestId = (~matcher, ~options=?, result) =>
+ _getAllByTestId(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.null(Dom.element) =
+ "queryByTestId";
+
+let queryByTestId = (~matcher, ~options=?, result) =>
+ _queryByTestId(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _queryAllByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ array(Dom.element) =
+ "queryAllByTestId";
+
+let queryAllByTestId = (~matcher, ~options=?, result) =>
+ _queryAllByTestId(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+[@mel.send.pipe: renderResult]
+external _findByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.Promise.t(Dom.element) =
+ "findByTestId";
+
+let findByTestId = (~matcher, ~options=?, result) =>
+ _findByTestId(result, ~matcher, ~options=Js.Undefined.fromOption(options));
+
+[@mel.send.pipe: renderResult]
+external _findAllByTestId:
+ (
+ ~matcher:
+ [@mel.unwrap] [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: Js.undefined(ByTestIdQuery.options)
+ ) =>
+ Js.Promise.t(array(Dom.element)) =
+ "findAllByTestId";
+
+let findAllByTestId = (~matcher, ~options=?, result) =>
+ _findAllByTestId(
+ result,
+ ~matcher,
+ ~options=Js.Undefined.fromOption(options),
+ );
+
+let render =
+ (
+ ~baseElement=?,
+ ~container=?,
+ ~hydrate=?,
+ ~wrapper=?,
+ ~queries=?,
+ element,
+ ) => {
+ let baseElement_ =
+ switch (container) {
+ | Some(container') => Js.Undefined.return(container')
+ | None => Js.Undefined.fromOption(baseElement)
+ };
+ let container_ = Js.Undefined.fromOption(container);
+
+ _render(
+ element,
+ {
+ "baseElement": baseElement_,
+ "container": container_,
+ "hydrate": Js.Undefined.fromOption(hydrate),
+ "wrapper": Js.Undefined.fromOption(wrapper),
+ "queries": Js.Undefined.fromOption(queries),
+ },
+ );
+};
+
+let debug = (~el=?, ~maxLengthToPrint=?) =>
+ _debug(
+ Js.Undefined.fromOption(el),
+ Js.Undefined.fromOption(maxLengthToPrint),
+ );
diff --git a/test/melange-testing-library/react/ReactTestingLibrary.rei b/test/melange-testing-library/react/ReactTestingLibrary.rei
new file mode 100644
index 000000000..e2608f7e5
--- /dev/null
+++ b/test/melange-testing-library/react/ReactTestingLibrary.rei
@@ -0,0 +1,702 @@
+module FireEvent: {
+ let abort: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let animationEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let animationIteration: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let animationStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let blur: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let canPlay: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let canPlayThrough: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let change: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let click: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let compositionEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let compositionStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let compositionUpdate: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let contextMenu: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let copy: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let cut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dblClick: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let doubleClick: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let drag: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragEnter: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragExit: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragLeave: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragOver: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let dragStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let drop: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let durationChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let emptied: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let encrypted: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let ended: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let error: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let focus: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let focusIn: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let focusOut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let input: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let invalid: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let keyDown: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let keyPress: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let keyUp: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let load: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let loadStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let loadedData: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let loadedMetadata: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseDown: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseEnter: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseLeave: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseMove: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseOut: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseOver: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let mouseUp: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let paste: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let pause: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let play: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let playing: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let progress: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let rateChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let scroll: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let seeked: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let seeking: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let select: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let stalled: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let submit: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let suspend: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let timeUpdate: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let touchCancel: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let touchEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let touchMove: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let touchStart: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let transitionEnd: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let volumeChange: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let waiting: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+ let wheel: (~eventInit: Js.t({..})=?, Dom.element) => unit;
+};
+
+type renderResult;
+type queries;
+type renderOptions = {
+ .
+ "container": Js.undefined(Dom.element),
+ "baseElement": Js.undefined(Dom.element),
+ "hydrate": Js.undefined(bool),
+ "wrapper": Js.undefined(Dom.element),
+ "queries": Js.undefined(queries),
+};
+
+[@mel.module "@testing-library/react"]
+external cleanup: unit => unit = "cleanup";
+
+[@mel.module "@testing-library/react"]
+external actAsync: (unit => Js.Promise.t('a)) => Js.Promise.t(unit) = "act";
+
+let act: (unit => unit) => unit;
+
+[@mel.get] external container: renderResult => Dom.element = "container";
+
+[@mel.get] external baseElement: renderResult => Dom.element = "baseElement";
+
+[@mel.send.pipe: renderResult] external unmount: unit => bool = "unmount";
+
+[@mel.send.pipe: renderResult]
+external asFragment: unit => Dom.element = "asFragment";
+
+// ByLabelText
+let getByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByLabelText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByLabelTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByPlaceholderText
+let getByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByPlaceholderText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByPlaceholderTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByText
+let getByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByAltText
+let getByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByAltText:
+ (
+ ~matcher: [
+ | `Func((string, Dom.element) => bool)
+ | `RegExp(Js.Re.t)
+ | `Str(string)
+ ],
+ ~options: DomTestingLibrary.ByAltTextQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByTitle
+let getByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByTitle:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTitleQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByDisplayValue
+let getByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByDisplayValue:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByDisplayValueQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByRole
+let getByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByRole:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByRoleQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+// ByTestId
+let getByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ Dom.element;
+
+let getAllByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let queryByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ Js.null(Dom.element);
+
+let queryAllByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ array(Dom.element);
+
+let findByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(Dom.element);
+
+let findAllByTestId:
+ (
+ ~matcher: [
+ | `Str(string)
+ | `RegExp(Js.Re.t)
+ | `Func((string, Dom.element) => bool)
+ ],
+ ~options: DomTestingLibrary.ByTestIdQuery.options=?,
+ renderResult
+ ) =>
+ Js.Promise.t(array(Dom.element));
+
+[@mel.send.pipe: renderResult]
+external rerender: React.element => unit = "rerender";
+
+let render:
+ (
+ ~baseElement: Dom.element=?,
+ ~container: Dom.element=?,
+ ~hydrate: bool=?,
+ ~wrapper: Dom.element=?,
+ ~queries: queries=?,
+ React.element
+ ) =>
+ renderResult;
+
+let debug:
+ (~el: Dom.element=?, ~maxLengthToPrint: int=?, renderResult) => unit;
diff --git a/test/melange-testing-library/react/dune b/test/melange-testing-library/react/dune
new file mode 100644
index 000000000..ecc0a0ab4
--- /dev/null
+++ b/test/melange-testing-library/react/dune
@@ -0,0 +1,7 @@
+(library
+ (name melange_testing_library_react)
+ (libraries reason-react melange_testing_library_dom)
+ (wrapped false)
+ (modes melange)
+ (preprocess
+ (pps melange.ppx)))