Skip to content

Commit 7797c10

Browse files
authored
test: configure Vitest browser mode and add basic bindings (#1192)
* test: configure Vitest browser mode and add basic bindings * add to CI * add interaction to test * fix test command * clean up CI names * split up CI jobs * install deps
1 parent a3ac8ed commit 7797c10

8 files changed

Lines changed: 887 additions & 11 deletions

File tree

.github/workflows/pull-request.yml

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,49 @@
1-
name: Test
1+
name: Pull Request
22
on: [pull_request]
33
jobs:
4-
build:
4+
Format:
55
runs-on: ubuntu-latest
66
steps:
7-
- uses: actions/checkout@v4
8-
- uses: actions/setup-node@v4
7+
- name: Checkout
8+
uses: actions/checkout@v4
9+
- name: Setup node
10+
uses: actions/setup-node@v4
911
with:
1012
node-version-file: ".node-version"
1113
cache: yarn
12-
- run: yarn
13-
- run: yarn build:res --warn-error +3+8+11+12+26+27+31+32+33+34+35+39+44+45+110
14-
- run: yarn test
15-
- run: yarn ci:format
14+
- name: Install dependencies
15+
run: yarn
16+
- name: Format check
17+
run: yarn ci:format
18+
Site_Checks:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
- name: Setup node
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version-file: ".node-version"
27+
cache: yarn
28+
- name: Install dependencies
29+
run: yarn
30+
- name: Test examples and hrefs
31+
run: yarn test
32+
Vitest:
33+
runs-on: ubuntu-latest
34+
steps:
35+
- name: Checkout
36+
uses: actions/checkout@v4
37+
- name: Setup node
38+
uses: actions/setup-node@v4
39+
with:
40+
node-version-file: ".node-version"
41+
cache: yarn
42+
- name: Install dependencies
43+
run: yarn
44+
- name: Build ReScript
45+
run: yarn build:res
46+
- name: Install Playwright
47+
run: yarn playwright install --with-deps
48+
- name: Vitest
49+
run: yarn ci:test

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ app/**/*.mjs
4848
app/**/*.jsx
4949
functions/**/*.mjs
5050
functions/**/*.jsx
51+
__tests__/**/*.mjs
52+
__tests__/**/*.jsx
5153
!_shims.mjs
5254
!_shims.jsx
5355

__tests__/Example.test.res

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
open Vitest
2+
3+
module Example = {
4+
@react.component
5+
let make = (~handleClick) =>
6+
<div>
7+
<button onClick=handleClick> {React.string("testing")} </button>
8+
</div>
9+
}
10+
11+
test("basic assertions", async () => {
12+
expect("foo")->toBe("foo")
13+
14+
expect(true)->toBe(true)
15+
})
16+
17+
test("component rendering", async () => {
18+
let callback = fn()
19+
let screen = await render(<Example handleClick=callback />)
20+
21+
await element(screen->getByText("testing"))->toBeVisible
22+
23+
let button = await screen->getByRole(#button)
24+
25+
await button->click
26+
27+
expect(callback)->toHaveBeenCalled
28+
})

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
"scripts": {
1313
"build:scripts": "yarn dlx tsdown@0.20.0 scripts/*.jsx -d _scripts --no-clean --ext .mjs",
1414
"build:generate-llms": "node _scripts/generate_llms.mjs",
15-
"build:res": "rescript build",
15+
"build:res": "rescript build --warn-error +3+8+11+12+26+27+31+32+33+34+35+39+44+45+110",
1616
"build:sync-bundles": "node scripts/sync-playground-bundles.mjs",
1717
"build:update-index": "yarn build:generate-llms && node _scripts/generate_feed.mjs > public/blog/feed.xml",
1818
"build:vite": "react-router build",
1919
"build": "yarn build:res && yarn build:scripts && yarn build:update-index && yarn build:vite",
2020
"ci:format": "prettier . --check --experimental-cli",
21+
"ci:test": "yarn vitest --run --browser.headless",
2122
"clean:res": "rescript clean",
2223
"convert-images": "auto-convert-images",
2324
"dev:res": "rescript watch",
@@ -28,7 +29,8 @@
2829
"prepare": "yarn build:res && yarn build:scripts && yarn build:update-index",
2930
"preview": "yarn build && static-server build/client",
3031
"reanalyze": "rescript-tools reanalyze -all-cmt .",
31-
"test": "node scripts/test-examples.mjs && node scripts/test-hrefs.mjs"
32+
"test": "node scripts/test-examples.mjs && node scripts/test-hrefs.mjs",
33+
"vitest": "vitest"
3234
},
3335
"dependencies": {
3436
"@babel/generator": "^7.24.7",
@@ -84,12 +86,14 @@
8486
"@tailwindcss/vite": "^4.1.13",
8587
"@types/react": "^19.2.2",
8688
"@vitejs/plugin-react": "^4.7.0",
89+
"@vitest/browser-playwright": "^4.0.18",
8790
"auto-image-converter": "^2.1.2",
8891
"chokidar": "^4.0.3",
8992
"dotenv": "^16.4.7",
9093
"jsdom": "^26.1.0",
9194
"lefthook": "^2.0.4",
9295
"lightningcss": "^1.30.1",
96+
"playwright": "^1.58.2",
9397
"prettier": "^3.6.2",
9498
"remark-cli": "^12.0.1",
9599
"search-insights": "^2.17.3",
@@ -100,6 +104,8 @@
100104
"vite-plugin-devtools-json": "^1.0.0",
101105
"vite-plugin-env-compatible": "^2.0.1",
102106
"vite-plugin-page-reload": "^0.2.2",
107+
"vitest": "^4.0.18",
108+
"vitest-browser-react": "^2.0.5",
103109
"wrangler": "^4.63.0"
104110
}
105111
}

rescript.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
"dependencies": ["@rescript/react", "@rescript/webapi"],
99
"compiler-flags": ["-open WebAPI.Global"],
1010
"sources": [
11+
{
12+
"dir": "__tests__",
13+
"subdirs": true,
14+
"type": "dev"
15+
},
1116
{
1217
"dir": "app",
1318
"subdirs": true

src/bindings/Vitest.res

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
type page
2+
type expect
3+
type screen
4+
type element
5+
type mock
6+
7+
/**
8+
* Vitest
9+
*/
10+
@module("vitest")
11+
external test: (string, unit => promise<unit>) => unit = "test"
12+
13+
@module("vitest") @scope("vi")
14+
external fn: unit => 'a => 'b = "fn"
15+
16+
@module("vitest")
17+
external expect: 'a => expect = "expect"
18+
19+
/**
20+
* vitest-browser-react
21+
*/
22+
@module("vitest-browser-react")
23+
external render: Jsx.element => promise<screen> = "render"
24+
25+
@module("vitest") @scope("expect")
26+
external element: 'a => element = "element"
27+
28+
/*
29+
* Locators
30+
*/
31+
@send
32+
external getByText: (screen, string) => element = "getByText"
33+
34+
@send
35+
external getByRole: (screen, [#button]) => promise<element> = "getByRole"
36+
37+
/**
38+
* Actions
39+
*/
40+
@send
41+
external click: element => promise<unit> = "click"
42+
43+
/**
44+
* Vitest assertions
45+
*/
46+
@send
47+
external toBe: (expect, 'a) => unit = "toBe"
48+
49+
@send
50+
external toHaveBeenCalled: expect => unit = "toHaveBeenCalled"
51+
52+
/**
53+
* Browser assertions
54+
*/
55+
@send
56+
external toBeVisible: element => promise<unit> = "toBeVisible"

vitest.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineConfig } from "vitest/config";
2+
import { playwright } from "@vitest/browser-playwright";
3+
import react from "@vitejs/plugin-react";
4+
5+
export default defineConfig({
6+
plugins: [react()],
7+
test: {
8+
include: ["__tests__/*.jsx"],
9+
browser: {
10+
enabled: true,
11+
provider: playwright(),
12+
// https://vitest.dev/config/browser/playwright
13+
instances: [{ browser: "chromium" }],
14+
},
15+
},
16+
});

0 commit comments

Comments
 (0)