rescript-vitest-extras 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarnrc.yml +1 -0
- package/CHANGELOG.md +16 -0
- package/README.md +187 -0
- package/package.json +47 -0
- package/rescript.json +34 -0
- package/src/VitestExtras.res +8 -0
- package/src/VitestExtras__Assert.res +627 -0
- package/src/VitestExtras__Assert.resi +302 -0
- package/src/VitestExtras__BrowserExpect.res +159 -0
- package/src/VitestExtras__BrowserExpect.resi +159 -0
- package/src/VitestExtras__BrowserLocator.res +190 -0
- package/src/VitestExtras__BrowserLocator.resi +190 -0
- package/src/VitestExtras__BrowserPage.res +119 -0
- package/src/VitestExtras__BrowserPage.resi +62 -0
- package/src/VitestExtras__BrowserReact.res +201 -0
- package/src/VitestExtras__BrowserReact.resi +201 -0
- package/src/VitestExtras__BrowserUserEvent.res +200 -0
- package/src/VitestExtras__BrowserUserEvent.resi +109 -0
- package/src/VitestExtras__Mock.res +639 -0
- package/src/VitestExtras__Mock.resi +432 -0
- package/src/VitestExtras__MockExpect.res +455 -0
package/.yarnrc.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nodeLinker: node-modules
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# rescript-vitest-extras
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a50a78c: Add ReScript bindings extending rescript-vitest with:
|
|
8
|
+
|
|
9
|
+
- `VitestExtras.Assert`: Chai-style assert API with ReScript-specific assertions for `option`, `result`, `Null.t`, `Nullable.t`, and `undefined`
|
|
10
|
+
- `VitestExtras.Mock`: Arity-specific mock function types (`mockFn0`–`mockFn5`) with mock context, implementation control, and return value stubbing
|
|
11
|
+
- `VitestExtras.MockExpect`: Expect matchers for mock assertions (`toHaveBeenCalled`, `toHaveBeenCalledWith`, `toHaveReturned`, etc.)
|
|
12
|
+
- `VitestExtras.BrowserLocator`: Locator API for browser-mode element queries, filtering, interaction, and element access
|
|
13
|
+
- `VitestExtras.BrowserPage`: `page` singleton with query methods, viewport control, and screenshot support
|
|
14
|
+
- `VitestExtras.BrowserUserEvent`: `userEvent` singleton for click, fill, type, hover, keyboard, drag-and-drop, and clipboard operations
|
|
15
|
+
- `VitestExtras.BrowserExpect`: `expect.element()` with 25 DOM assertion matchers (visibility, state, content, attributes, form values)
|
|
16
|
+
- `VitestExtras.BrowserReact`: `render` and `renderHook` bindings for `vitest-browser-react` with auto-cleanup and a `Pure` submodule
|
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# rescript-vitest-extras
|
|
2
|
+
|
|
3
|
+
Additional ReScript bindings for [Vitest](https://vitest.dev/), extending [rescript-vitest](https://github.com/cometkim/rescript-vitest).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install rescript-vitest-extras rescript-vitest vitest
|
|
9
|
+
# or
|
|
10
|
+
yarn add rescript-vitest-extras rescript-vitest vitest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Add to your `rescript.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"dependencies": ["rescript-vitest", "rescript-vitest-extras"]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Modules
|
|
22
|
+
|
|
23
|
+
### VitestExtras.Assert
|
|
24
|
+
|
|
25
|
+
Chai-style assert API bindings with ReScript-specific assertions for `option`, `result`, `Null.t`, `Nullable.t`, and `undefined`.
|
|
26
|
+
|
|
27
|
+
```rescript
|
|
28
|
+
open Vitest
|
|
29
|
+
module A = VitestExtras.Assert
|
|
30
|
+
|
|
31
|
+
test("equality", _ => {
|
|
32
|
+
A.equal(1, 1)
|
|
33
|
+
A.deepEqual([1, 2, 3], [1, 2, 3])
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test("option assertions", _ => {
|
|
37
|
+
A.Option.isSome(Some(42))
|
|
38
|
+
A.Option.isNone(None)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test("result assertions", _ => {
|
|
42
|
+
A.Result.isOk(Ok(42))
|
|
43
|
+
A.Result.isError(Error("fail"))
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test("nullable assertions", _ => {
|
|
47
|
+
let value: Nullable.t<int> = Nullable.make(42)
|
|
48
|
+
A.Nullable.exists(value)
|
|
49
|
+
A.Nullable.isNotNull(value)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test("array assertions", _ => {
|
|
53
|
+
A.Array.includes([1, 2, 3], 2)
|
|
54
|
+
A.Array.sameMembers([1, 2, 3], [3, 1, 2])
|
|
55
|
+
A.Array.lengthOf([1, 2], 2)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("string assertions", _ => {
|
|
59
|
+
A.String.includes("hello world", "world")
|
|
60
|
+
A.String.isEmpty("")
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("numeric comparisons", _ => {
|
|
64
|
+
A.isAbove(10.0, 5.0)
|
|
65
|
+
A.closeTo(1.5, 1.0, ~delta=1.0)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("exceptions", _ => {
|
|
69
|
+
A.throws(() => JsError.throwWithMessage("error"))
|
|
70
|
+
A.doesNotThrow(() => ())
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
All assertions accept an optional `~message` parameter for custom failure messages.
|
|
75
|
+
|
|
76
|
+
### VitestExtras.Mock
|
|
77
|
+
|
|
78
|
+
Arity-specific mock function types with full access to mock context, implementation control, and return value stubbing.
|
|
79
|
+
|
|
80
|
+
```rescript
|
|
81
|
+
open Vitest
|
|
82
|
+
open VitestExtras
|
|
83
|
+
|
|
84
|
+
module M = Mock
|
|
85
|
+
|
|
86
|
+
describe("mock functions", () => {
|
|
87
|
+
test("create and call mocks", _ => {
|
|
88
|
+
// Create with implementation
|
|
89
|
+
let add = M.fnWithImpl2((a, b) => a + b)
|
|
90
|
+
let fn = add->M.MockFn2.toFunction
|
|
91
|
+
|
|
92
|
+
A.equal(fn(2, 3), 5)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test("stub return values", _ => {
|
|
96
|
+
let mock = M.fn0()->M.MockFn0.mockReturnValue(42)
|
|
97
|
+
let fn = mock->M.MockFn0.toFunction
|
|
98
|
+
|
|
99
|
+
A.equal(fn(), 42)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test("access call history", _ => {
|
|
103
|
+
let mock = M.fnWithImpl1(x => x * 2)
|
|
104
|
+
let fn = mock->M.MockFn1.toFunction
|
|
105
|
+
|
|
106
|
+
let _ = fn(5)
|
|
107
|
+
let _ = fn(10)
|
|
108
|
+
|
|
109
|
+
let ctx = mock->M.MockFn1.mock
|
|
110
|
+
A.Array.lengthOf(ctx.calls, 2)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test("mock implementation once", _ => {
|
|
114
|
+
let mock = M.fn0()
|
|
115
|
+
->M.MockFn0.mockReturnValueOnce(1)
|
|
116
|
+
->M.MockFn0.mockReturnValueOnce(2)
|
|
117
|
+
->M.MockFn0.mockReturnValue(999)
|
|
118
|
+
let fn = mock->M.MockFn0.toFunction
|
|
119
|
+
|
|
120
|
+
A.equal(fn(), 1)
|
|
121
|
+
A.equal(fn(), 2)
|
|
122
|
+
A.equal(fn(), 999)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test("async mocks", async () => {
|
|
126
|
+
let mock = M.fn0()->M.MockFn0.mockResolvedValue(42)
|
|
127
|
+
let fn = mock->M.MockFn0.toFunction
|
|
128
|
+
|
|
129
|
+
let result = await fn()
|
|
130
|
+
A.equal(result, 42)
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Available arities: `mockFn0` through `mockFn5`, each with corresponding `MockFn0` through `MockFn5` modules.
|
|
136
|
+
|
|
137
|
+
### VitestExtras.MockExpect
|
|
138
|
+
|
|
139
|
+
Expect matchers for mock function assertions.
|
|
140
|
+
|
|
141
|
+
```rescript
|
|
142
|
+
open Vitest
|
|
143
|
+
open VitestExtras
|
|
144
|
+
|
|
145
|
+
module M = Mock
|
|
146
|
+
module ME = MockExpect
|
|
147
|
+
|
|
148
|
+
test("mock matchers", _ => {
|
|
149
|
+
let mock = M.fnWithImpl1(x => x + 1)
|
|
150
|
+
let fn = mock->M.MockFn1.toFunction
|
|
151
|
+
|
|
152
|
+
let _ = fn(5)
|
|
153
|
+
|
|
154
|
+
expect(mock)->ME.toHaveBeenCalled
|
|
155
|
+
expect(mock)->ME.toHaveBeenCalledTimes(1)
|
|
156
|
+
expect(mock)->ME.toHaveBeenCalledWith1(5)
|
|
157
|
+
expect(mock)->ME.toHaveReturnedWith(6)
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Module Organization
|
|
162
|
+
|
|
163
|
+
This library uses the `VitestExtras__` namespace for internal modules with a public `VitestExtras` entry point that exports all public APIs. You can access modules in two ways:
|
|
164
|
+
|
|
165
|
+
**Recommended** — via the public `VitestExtras` entry point:
|
|
166
|
+
```rescript
|
|
167
|
+
open VitestExtras
|
|
168
|
+
module A = Assert
|
|
169
|
+
module M = Mock
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Alternatively** — use fully qualified internal names:
|
|
173
|
+
```rescript
|
|
174
|
+
module A = VitestExtras__Assert
|
|
175
|
+
module M = VitestExtras__Mock
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Mock Function Types
|
|
179
|
+
|
|
180
|
+
| Type | Signature |
|
|
181
|
+
| ----------------------------------- | ------------------------------ |
|
|
182
|
+
| `mockFn0<'ret>` | `() => 'ret` |
|
|
183
|
+
| `mockFn1<'a, 'ret>` | `'a => 'ret` |
|
|
184
|
+
| `mockFn2<'a, 'b, 'ret>` | `('a, 'b) => 'ret` |
|
|
185
|
+
| `mockFn3<'a, 'b, 'c, 'ret>` | `('a, 'b, 'c) => 'ret` |
|
|
186
|
+
| `mockFn4<'a, 'b, 'c, 'd, 'ret>` | `('a, 'b, 'c, 'd) => 'ret` |
|
|
187
|
+
| `mockFn5<'a, 'b, 'c, 'd, 'e, 'ret>` | `('a, 'b, 'c, 'd, 'e) => 'ret` |
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rescript-vitest-extras",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"packageManager": "yarn@4.12.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"res:build": "rescript build",
|
|
7
|
+
"res:clean": "rescript clean",
|
|
8
|
+
"res:watch": "rescript watch",
|
|
9
|
+
"test": "vitest",
|
|
10
|
+
"test:browser": "vitest --config vitest.browser.config.mjs"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@changesets/cli": "^2.29.8",
|
|
14
|
+
"@playwright/test": "^1.48.0",
|
|
15
|
+
"@rescript/react": "^0.14.1",
|
|
16
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
17
|
+
"@vitest/browser": "^3.2.4",
|
|
18
|
+
"@vitest/browser-playwright": "^4.0.18",
|
|
19
|
+
"@vitest/browser-preview": "^4.0.18",
|
|
20
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
21
|
+
"@vitest/ui": "^4.0.18",
|
|
22
|
+
"react": "^19.1.0",
|
|
23
|
+
"react-dom": "^19.1.0",
|
|
24
|
+
"rescript": "^12.1.0",
|
|
25
|
+
"rescript-vitest": "^2.1.1",
|
|
26
|
+
"vite": "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0",
|
|
27
|
+
"vitest": "^4.0.18",
|
|
28
|
+
"vitest-browser-react": "^2.0.5"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@rescript/react": "^0.14.0",
|
|
32
|
+
"rescript-vitest": "^2.1.1",
|
|
33
|
+
"vitest": "^3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"@rescript/react": {
|
|
37
|
+
"optional": true
|
|
38
|
+
},
|
|
39
|
+
"@vitest/browser": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"resolutions": {},
|
|
43
|
+
"vitest-browser-react": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/rescript.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rescript-vitest-extras",
|
|
3
|
+
"dependencies": ["rescript-vitest", "@rescript/react"],
|
|
4
|
+
"sources": [
|
|
5
|
+
{
|
|
6
|
+
"dir": "src",
|
|
7
|
+
"subdirs": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"dir": "__tests__",
|
|
11
|
+
"type": "dev",
|
|
12
|
+
"subdirs": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"dir": "examples",
|
|
16
|
+
"type": "dev",
|
|
17
|
+
"subdirs": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"dir": "__browser_tests__",
|
|
21
|
+
"type": "dev",
|
|
22
|
+
"subdirs": true
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"package-specs": {
|
|
26
|
+
"module": "esmodule",
|
|
27
|
+
"suffix": ".res.mjs",
|
|
28
|
+
"in-source": true
|
|
29
|
+
},
|
|
30
|
+
"jsx": {
|
|
31
|
+
"version": 4,
|
|
32
|
+
"mode": "automatic"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module Assert = VitestExtras__Assert
|
|
2
|
+
module Mock = VitestExtras__Mock
|
|
3
|
+
module MockExpect = VitestExtras__MockExpect
|
|
4
|
+
module BrowserLocator = VitestExtras__BrowserLocator
|
|
5
|
+
module BrowserPage = VitestExtras__BrowserPage
|
|
6
|
+
module BrowserUserEvent = VitestExtras__BrowserUserEvent
|
|
7
|
+
module BrowserExpect = VitestExtras__BrowserExpect
|
|
8
|
+
module BrowserReact = VitestExtras__BrowserReact
|