@colisweb/rescript-toolkit 2.25.0 → 2.26.1
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/package.json +1 -1
- package/src/mock/MockOverlay.res +43 -0
- package/src/mock/MockOverlay.resi +4 -0
- package/src/mock/index.md +94 -0
- package/src/ui/Toolkit__Ui_DropdownList.res +3 -1
- package/src/ui/Toolkit__Ui_DropdownList.resi +1 -0
- package/src/vendors/Browser.res +2 -0
- package/src/vendors/Browser.resi +1 -0
- package/src/vendors/Msw.res +32 -0
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
let localStorageKey = "@colisweb/mock"
|
|
2
|
+
|
|
3
|
+
@react.component
|
|
4
|
+
let make = (~worker: Msw.worker, ~children) => {
|
|
5
|
+
let (mockEnabled, setMock) = React.useState(() =>
|
|
6
|
+
Browser.LocalStorage.getItem(localStorageKey)
|
|
7
|
+
->Js.Nullable.toOption
|
|
8
|
+
->Option.mapWithDefault(false, bool_of_string)
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
React.useEffect1(() => {
|
|
12
|
+
if mockEnabled {
|
|
13
|
+
worker->Msw.start
|
|
14
|
+
Browser.LocalStorage.setItem(localStorageKey, Js.Nullable.return("true"))
|
|
15
|
+
} else {
|
|
16
|
+
worker->Msw.stop
|
|
17
|
+
Browser.LocalStorage.removeItem(localStorageKey)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
None
|
|
21
|
+
}, [mockEnabled])
|
|
22
|
+
|
|
23
|
+
<React.Suspense fallback={<Toolkit__Ui_SpinnerFullScreen />}>
|
|
24
|
+
<label
|
|
25
|
+
className={`fixed top-2 left-1/2 flex flex-row gap-2 items-center justify-center ${mockEnabled
|
|
26
|
+
? "bg-success-100 border-success-400 text-success-700"
|
|
27
|
+
: "bg-neutral-100"} p-1 border rounded-lg z-50 cursor-pointer`}>
|
|
28
|
+
<span> {"Mock"->React.string} </span>
|
|
29
|
+
<input
|
|
30
|
+
type_={"checkbox"}
|
|
31
|
+
checked={mockEnabled}
|
|
32
|
+
onChange={event => {
|
|
33
|
+
let checked = (event->ReactEvent.Form.target)["checked"]
|
|
34
|
+
|
|
35
|
+
setMock(_ => checked)
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
</label>
|
|
39
|
+
{children}
|
|
40
|
+
</React.Suspense>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let default = make
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Mock
|
|
2
|
+
|
|
3
|
+
We use [msw](https://mswjs.io) for mocking API content.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Install the package
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
yarn add msw --dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Wrap the App for dev only
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import React from "react";
|
|
17
|
+
import ReactDOM from "react-dom";
|
|
18
|
+
import "@colisweb/rescript-toolkit/src/ui/styles.css";
|
|
19
|
+
import { make as App } from "../lib/es6_global/src/App.bs";
|
|
20
|
+
import { make as Spinner } from "@colisweb/rescript-toolkit/lib/es6_global/src/ui/Toolkit__Ui_SpinnerFullScreen.bs.js";
|
|
21
|
+
import { make as AppWithMock } from "@colisweb/rescript-toolkit/lib/es6_global/src/mock/AppWithMock.bs";
|
|
22
|
+
|
|
23
|
+
const root = ReactDOM.createRoot(document.getElementById("root"));
|
|
24
|
+
|
|
25
|
+
if (import.meta.env.DEV) {
|
|
26
|
+
import("../lib/es6_global/mocks/Mock.bs").then(({ worker }) => {
|
|
27
|
+
root.render(
|
|
28
|
+
<AppWithMock worker={worker}>
|
|
29
|
+
<App />
|
|
30
|
+
</AppWithMock>
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
root.render(
|
|
35
|
+
<React.Suspense fallback={<Spinner />}>
|
|
36
|
+
<App />
|
|
37
|
+
</React.Suspense>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Define the mock
|
|
43
|
+
|
|
44
|
+
```rescript
|
|
45
|
+
/* Mock_Page_X.res */
|
|
46
|
+
|
|
47
|
+
open Identifiers
|
|
48
|
+
|
|
49
|
+
let mocks = [
|
|
50
|
+
Msw.Rest.get(
|
|
51
|
+
"https://api.url",
|
|
52
|
+
(req, res, ctx) => {
|
|
53
|
+
open ColiswebApi.V5.Transporter.GetContactsWithParameters.Config
|
|
54
|
+
let _emptyResponse = []
|
|
55
|
+
let defaultResponse = [
|
|
56
|
+
{
|
|
57
|
+
id: ContactIdString.make("1"),
|
|
58
|
+
firstName: "Thomas",
|
|
59
|
+
lastName: "Deconinck",
|
|
60
|
+
email: "dck@colisweb.com",
|
|
61
|
+
primaryPhone: "0123456789",
|
|
62
|
+
parameters: {
|
|
63
|
+
id: ParameterId.make("1"),
|
|
64
|
+
email: true,
|
|
65
|
+
sms: true,
|
|
66
|
+
call: true,
|
|
67
|
+
},
|
|
68
|
+
carrier: None,
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
let transporterId = req.params["transporterId"]
|
|
73
|
+
|
|
74
|
+
switch transporterId {
|
|
75
|
+
| "9" => res(Msw.Ctx.json(ctx, defaultResponse))
|
|
76
|
+
| _ => ()
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
),
|
|
80
|
+
Msw.Rest.put(
|
|
81
|
+
"https://api.url",
|
|
82
|
+
(_req, res, ctx) => {
|
|
83
|
+
res(Msw.Ctx.status(ctx, 200))
|
|
84
|
+
},
|
|
85
|
+
),
|
|
86
|
+
]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Define the worker with the mock at the top of your app.
|
|
90
|
+
|
|
91
|
+
```rescript
|
|
92
|
+
/* Mock.res */
|
|
93
|
+
let worker = Msw.setupWorker([]->Array.concat(Mock_Page_X.mocks))
|
|
94
|
+
```
|
|
@@ -7,6 +7,7 @@ type item = {
|
|
|
7
7
|
icon: React.element,
|
|
8
8
|
label: React.element,
|
|
9
9
|
onClick: unit => unit,
|
|
10
|
+
className: string,
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
@react.component
|
|
@@ -142,12 +143,13 @@ let make = (
|
|
|
142
143
|
isXs ? "bg-white p-2 mx-2 shadow rounded-t-lg" : "",
|
|
143
144
|
])}>
|
|
144
145
|
{items
|
|
145
|
-
->Array.mapWithIndex((i, {icon, label, onClick}) => {
|
|
146
|
+
->Array.mapWithIndex((i, {icon, label, onClick, className}) => {
|
|
146
147
|
<div
|
|
147
148
|
onClick={_ => onClick()}
|
|
148
149
|
className={cx([
|
|
149
150
|
"flex flex-row gap-4 items-center py-2 hover:bg-neutral-100 focus:bg-neutral-100 cursor-pointer",
|
|
150
151
|
i == 0 ? "" : "border-t",
|
|
152
|
+
className,
|
|
151
153
|
])}
|
|
152
154
|
key={i->Int.toString}>
|
|
153
155
|
{icon} {label}
|
package/src/vendors/Browser.res
CHANGED
|
@@ -3,6 +3,8 @@ module LocalStorage = {
|
|
|
3
3
|
external getItem: string => Js.Nullable.t<string> = "localStorage.getItem"
|
|
4
4
|
@val
|
|
5
5
|
external setItem: (string, Js.Nullable.t<string>) => unit = "localStorage.setItem"
|
|
6
|
+
@val
|
|
7
|
+
external removeItem: string => unit = "localStorage.removeItem"
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
module Location = {
|
package/src/vendors/Browser.resi
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type mock
|
|
2
|
+
type worker
|
|
3
|
+
|
|
4
|
+
@module("msw") @variadic
|
|
5
|
+
external setupWorker: array<mock> => worker = "setupWorker"
|
|
6
|
+
|
|
7
|
+
@send
|
|
8
|
+
external start: worker => unit = "start"
|
|
9
|
+
@send
|
|
10
|
+
external stop: worker => unit = "stop"
|
|
11
|
+
|
|
12
|
+
module Ctx = {
|
|
13
|
+
type t
|
|
14
|
+
|
|
15
|
+
@send
|
|
16
|
+
external json: (t, 'a) => 'b = "json"
|
|
17
|
+
@send
|
|
18
|
+
external status: (t, 'a) => 'b = "status"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module Rest = {
|
|
22
|
+
type req<'params> = {params: 'params}
|
|
23
|
+
|
|
24
|
+
@module("msw") @scope("rest")
|
|
25
|
+
external get: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "get"
|
|
26
|
+
@module("msw") @scope("rest")
|
|
27
|
+
external put: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "put"
|
|
28
|
+
@module("msw") @scope("rest")
|
|
29
|
+
external post: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "post"
|
|
30
|
+
@module("msw") @scope("rest")
|
|
31
|
+
external delete: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "delete"
|
|
32
|
+
}
|