@servicetitan/docs-uikit 31.5.0 → 31.6.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/docs/BREAKING_CHANGES.mdx +1 -2
- package/docs/ajax-handlers/ajax-handlers.mdx +12 -0
- package/docs/ajax-handlers/init-ajax-handlers-parse-dates.mdx +74 -0
- package/docs/{ajax-handlers.mdx → ajax-handlers/with-microservice.mdx} +33 -29
- package/docs/datadog-rum.mdx +133 -0
- package/docs/startup/review.mdx +42 -0
- package/docs/startup/test.mdx +197 -3
- package/package.json +2 -2
|
@@ -63,14 +63,13 @@ title: BREAKING CHANGES
|
|
|
63
63
|
|
|
64
64
|
### [@servicetitan/ajax-handlers](./ajax-handlers)
|
|
65
65
|
|
|
66
|
-
- Changed [**withMicroservice**](./ajax-handlers#parameters) arguments to a single options object.
|
|
66
|
+
- Changed [**withMicroservice**](./ajax-handlers/with-microservice#parameters) arguments to a single options object.
|
|
67
67
|
|
|
68
68
|
## v24.0.0
|
|
69
69
|
|
|
70
70
|
### [@servicetitan/startup](./startup)
|
|
71
71
|
|
|
72
72
|
- Upgraded **Typescript** from v4 to v5, which adds correctness improvements that will reveal previously undetected ambiguities. In particular,
|
|
73
|
-
|
|
74
73
|
- Type checks for enums are stricter because all **enum** values get their own type
|
|
75
74
|
- **string** and **boolean** values aren't implicitly converted to numbers. Use the `+` operator to explicitly convert values to numbers in mathematical expressions. (e.g., `return +str > 42;`)
|
|
76
75
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AJAX Handlers
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
#### [CHANGELOG (@servicetitan/ajax-handlers)](https://github.com/servicetitan/uikit/blob/master/packages/ajax-handlers/CHANGELOG.md)
|
|
6
|
+
|
|
7
|
+
`@servicetitan/ajax-handlers` provides utilities for handling AJAX requests, authentication, and response processing in ServiceTitan applications. It includes automatic date parsing, authentication wrappers for protected resources, and comprehensive error handling.
|
|
8
|
+
|
|
9
|
+
## API
|
|
10
|
+
|
|
11
|
+
- [withMicroservice](./with-microservice.mdx) - Use `withMicroservice` to wrap components and authenticate requests to protected resources with support for Bearer and Token Server authentication.
|
|
12
|
+
- [initAjaxHandlersParseDates](./init-ajax-handlers-parse-dates.mdx) - Use `initAjaxHandlersParseDates` to automatically transform date strings in axios responses into JavaScript Date objects.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: initAjaxHandlersParseDates
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
`initAjaxHandlersParseDates` is a function that automatically transforms date strings in axios responses into JavaScript Date objects. This eliminates the need for manual date parsing throughout your application.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Call this function once in your application's initialization code, typically before making any axios requests:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { initAjaxHandlersParseDates } from '@servicetitan/ajax-handlers';
|
|
13
|
+
|
|
14
|
+
// Initialize date parsing for all axios responses
|
|
15
|
+
initAjaxHandlersParseDates();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
The function adds a response transformer to the global axios defaults that:
|
|
21
|
+
|
|
22
|
+
1. Automatically detects and parses date strings in response data
|
|
23
|
+
2. Recursively traverses objects and arrays to find date strings
|
|
24
|
+
3. Preserves other data types unchanged (including Blobs)
|
|
25
|
+
4. Handles parsing errors gracefully by returning the original data
|
|
26
|
+
|
|
27
|
+
## Supported Date Formats
|
|
28
|
+
|
|
29
|
+
The parser recognizes two date formats commonly used in APIs:
|
|
30
|
+
|
|
31
|
+
### ISO 8601 Format
|
|
32
|
+
|
|
33
|
+
Supports standard ISO date strings with optional time zones and milliseconds:
|
|
34
|
+
|
|
35
|
+
- `2024-03-15T10:30:45Z`
|
|
36
|
+
- `2024-03-15T10:30:45.123Z`
|
|
37
|
+
- `2024-03-15T10:30:45+05:00`
|
|
38
|
+
- `2024-03-15T10:30:45.789-08:00`
|
|
39
|
+
|
|
40
|
+
### .NET JSON Date Format
|
|
41
|
+
|
|
42
|
+
Supports the legacy .NET JSON date format:
|
|
43
|
+
|
|
44
|
+
- `/Date(1710504645000)/`
|
|
45
|
+
- `/Date(1710504645000-0800)/`
|
|
46
|
+
- `/Date(-62135596800000)/` (negative timestamps for dates before 1970)
|
|
47
|
+
|
|
48
|
+
## Example
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import axios from 'axios';
|
|
52
|
+
import { initAjaxHandlersParseDates } from '@servicetitan/ajax-handlers';
|
|
53
|
+
|
|
54
|
+
// Initialize date parsing once
|
|
55
|
+
initAjaxHandlersParseDates();
|
|
56
|
+
|
|
57
|
+
// Now all axios responses will have dates automatically parsed
|
|
58
|
+
const response = await axios.get('/api/users/123');
|
|
59
|
+
|
|
60
|
+
// response.data might look like:
|
|
61
|
+
// {
|
|
62
|
+
// id: 123,
|
|
63
|
+
// name: 'John Doe',
|
|
64
|
+
// createdAt: Date object (not a string!),
|
|
65
|
+
// lastLogin: Date object (not a string!),
|
|
66
|
+
// metadata: {
|
|
67
|
+
// updatedAt: Date object (not a string!)
|
|
68
|
+
// }
|
|
69
|
+
// }
|
|
70
|
+
|
|
71
|
+
// You can immediately use Date methods
|
|
72
|
+
console.log(response.data.createdAt.getFullYear());
|
|
73
|
+
console.log(response.data.lastLogin.toLocaleDateString());
|
|
74
|
+
```
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
2
|
+
title: withMicroservice
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
#### [CHANGELOG (@servicetitan/ajax-handlers)](https://github.com/servicetitan/uikit/blob/master/packages/ajax-handlers/CHANGELOG.md)
|
|
6
|
-
|
|
7
|
-
## withMicroservice
|
|
8
|
-
|
|
9
5
|
`withMicroservice` is a higher-order function that wraps a component and authenticates
|
|
10
6
|
its requests to protected resources.
|
|
11
7
|
|
|
12
|
-
|
|
8
|
+
## Usage
|
|
13
9
|
|
|
14
10
|
The best way to use `withMicroservice` is to wrap the component in the ES module body. E.g.,
|
|
15
11
|
|
|
@@ -54,7 +50,7 @@ const App = () => {
|
|
|
54
50
|
}
|
|
55
51
|
```
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
## Parameters
|
|
58
54
|
|
|
59
55
|
`withMicroservice` accepts an object with the following properties:
|
|
60
56
|
|
|
@@ -70,27 +66,27 @@ const App = () => {
|
|
|
70
66
|
| `preAuthenticateCallback` | `(error?: any) => void` | (optional) callback to call after pre-authentication succeeds or fails. If pre-authentication fails, the error is passed to the first parameter of the callback. |
|
|
71
67
|
| `tokens` | `Symbol[]` | (optional) symbols to use to provide `baseURL` to autogenerated API services and child components |
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
### authAdapter{#auth-adapter}
|
|
74
70
|
|
|
75
71
|
Use `authAdapter` to select the authentication scheme. One of,
|
|
76
72
|
|
|
77
|
-
| Value
|
|
78
|
-
|
|
|
79
|
-
| "bearer"
|
|
80
|
-
| "token"
|
|
73
|
+
| Value | Description |
|
|
74
|
+
| :-------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
75
|
+
| "bearer" | **Bearer** authentication sends the bearer token returned by `authURL` in the **Authorization** header of requests. Uses BearerTokenAuth adapter. |
|
|
76
|
+
| "token" | **Token** authentication uses the Token Server's "silent login" protocol to add secure cookies to requests. Uses TokenServerAuth adapter. |
|
|
81
77
|
| `(context: WithMicroserviceContext) => AuthAdapter` | Custom authentication uses the adapter returned by a function to decorate requests. |
|
|
82
78
|
|
|
83
79
|
See [Authentication Adapters](#authentication-adapters) for more information.
|
|
84
80
|
|
|
85
|
-
|
|
81
|
+
### authUrl
|
|
86
82
|
|
|
87
83
|
The authentication endpoint for protected resources.
|
|
88
84
|
|
|
89
|
-
-
|
|
85
|
+
- For **Bearer** authentication, this is the endpoint that returns the bearer token to send in **Authorization** headers. Defaults to `${baseURL}/auth`.
|
|
90
86
|
|
|
91
|
-
-
|
|
87
|
+
- For **Token server** authentication, this is the "silent login" endpoint. Defaults to `${baseURL}/bff/silent-login`.
|
|
92
88
|
|
|
93
|
-
|
|
89
|
+
### preAuthenticate{#pre-authenticate}
|
|
94
90
|
|
|
95
91
|
Controls when authentication happens:
|
|
96
92
|
|
|
@@ -101,9 +97,9 @@ Controls when authentication happens:
|
|
|
101
97
|
|
|
102
98
|
When using Token Server authentication, authentication is always performed after the component is loaded and this value is ignored.
|
|
103
99
|
|
|
104
|
-
|
|
100
|
+
### tokens
|
|
105
101
|
|
|
106
|
-
The main purpose of `tokens` is to [provide](
|
|
102
|
+
The main purpose of `tokens` is to [provide](../react-ioc#provide) the `baseURL` to autogenerated API services.
|
|
107
103
|
For example,
|
|
108
104
|
|
|
109
105
|
```tsx
|
|
@@ -138,11 +134,11 @@ const Component = () => {
|
|
|
138
134
|
}
|
|
139
135
|
```
|
|
140
136
|
|
|
141
|
-
|
|
137
|
+
## Authentication Adapters{#authentication-adapters}
|
|
142
138
|
|
|
143
139
|
`withMicroservice` uses authentication adapters in order to perform authentication in different ways depending on your needs.
|
|
144
140
|
|
|
145
|
-
|
|
141
|
+
### BearerTokenAuth
|
|
146
142
|
|
|
147
143
|
The default adapter is the `BearerTokenAuth` adapter. When authentication occurs, a request is sent to the `authURL` in order to retrieve a token. Then any requests made using the `baseURL` will add the `Authorization: Bearer ...` header with the stored token.
|
|
148
144
|
|
|
@@ -156,7 +152,7 @@ const App = withMicroservice({
|
|
|
156
152
|
});
|
|
157
153
|
```
|
|
158
154
|
|
|
159
|
-
|
|
155
|
+
### TokenServerAuth{#token-server-auth}
|
|
160
156
|
|
|
161
157
|
The `TokenServerAuth` adapter allows you to authenticate with a backend that is using the `ServiceTitan.Ium.Bff` NuGet package ([see TokenServer documentation for details](/docs/projects/ium/tokenserver-new-app-integration/)).
|
|
162
158
|
|
|
@@ -177,8 +173,8 @@ const App = withMicroservice({
|
|
|
177
173
|
```tsx title="Custom adapter"
|
|
178
174
|
const options: TokenServerAuthOptions = {
|
|
179
175
|
authInfoURL: '/custom/authinfo',
|
|
180
|
-
onError: (defaultErrorHandler) => {
|
|
181
|
-
console.error(
|
|
176
|
+
onError: (defaultErrorHandler, error) => {
|
|
177
|
+
console.error(error, error.data);
|
|
182
178
|
defaultErrorHandler();
|
|
183
179
|
},
|
|
184
180
|
};
|
|
@@ -189,12 +185,20 @@ const App = withMicroservice({
|
|
|
189
185
|
});
|
|
190
186
|
```
|
|
191
187
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
| `
|
|
188
|
+
#### TokenServerAuthOptions
|
|
189
|
+
|
|
190
|
+
| Name | Type | Description |
|
|
191
|
+
| :------------ | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
|
|
192
|
+
| `authInfoURL` | `string` | (optional) URL to fetch authentication parameters from. Defaults to `'/bff/authinfo'`. |
|
|
193
|
+
| `onError` | `(defaultErrorHandler: () => void, error: Error) => void;` | (optional) Callback to call when an error occurs during authentication. Defaults to reloading the page a maximum of 1 time. |
|
|
194
|
+
|
|
195
|
+
The `onError` callback is passed the following arguments:
|
|
196
|
+
|
|
197
|
+
| Name | Type | Description |
|
|
198
|
+
| :-------------------- | :--------- | :------------------------------------------------------------------------------------------------- |
|
|
199
|
+
| `defaultErrorHandler` | `Function` | The default error handler. |
|
|
200
|
+
| `error` | `Error` | An error object with a `data` property that contains the data associated with the failure, if any. |
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
## Authorization
|
|
199
203
|
|
|
200
204
|
`withMicroservice` currently only assists with performing authentication for requests of protected resources. There are currently no plans to implement authorization until we see concrete Token Server usage examples by product teams. If you find that having any sort of implementation for authorization would be helpful, especially in regards to Token Server implementation, please bring any ideas or discussions to the Frontend Platform team's attention so that we can create a platform solution.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: DataDog RUM
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
#### [CHANGELOG (@servicetitan/datadog-rum)](https://github.com/servicetitan/uikit/blob/master/packages/datadog-rum/CHANGELOG.md)
|
|
6
|
+
|
|
7
|
+
[`@servicetitan/datadog-rum`](https://github.com/servicetitan/uikit/tree/master/packages/datadog-rum) helps configure DataDog RUM JS SDK in standalone applications. It enriches RUM events with information useful for application and MFE monitoring, and troubleshooting.
|
|
8
|
+
|
|
9
|
+
## Configuration snippet
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { beforeSend, DatadogProvider } from '@servicetitan/datadog-rum';
|
|
13
|
+
import { datadogRum } from '@datadog/browser-rum';
|
|
14
|
+
|
|
15
|
+
const isEnabled = /.*go\d*\.servicetitan\.com/.test(window.location.hostname);
|
|
16
|
+
|
|
17
|
+
if (isEnabled) {
|
|
18
|
+
datadogRum.init({
|
|
19
|
+
applicationId: '<APPLICATION_ID>',
|
|
20
|
+
clientToken: '<CLIENT_TOKEN>',
|
|
21
|
+
site: 'datadoghq.com',
|
|
22
|
+
service: '<SERVICE_NAME>',
|
|
23
|
+
env: '<ENV_NAME>',
|
|
24
|
+
version: '<APPLICATION_VERSION>',
|
|
25
|
+
sessionSampleRate: 100,
|
|
26
|
+
sessionReplaySampleRate: 0,
|
|
27
|
+
defaultPrivacyLevel: 'mask-user-input',
|
|
28
|
+
beforeSend: beforeSend(),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const Root = () => {
|
|
33
|
+
const user = useCurrentUser(); // application-specific hook that identifies the user
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<DatadogProvider isEnabled={isEnabled} user={user}>
|
|
37
|
+
<Application />
|
|
38
|
+
</DatadogProvider>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## DatadogProvider
|
|
44
|
+
|
|
45
|
+
`DatadogProvider` is a higher-order component that supplies RUM SDK with:
|
|
46
|
+
|
|
47
|
+
- Information about the user session
|
|
48
|
+
- Sanitized view event names (`@view.name`) when hash-based routing is used
|
|
49
|
+
|
|
50
|
+
### Usage
|
|
51
|
+
|
|
52
|
+
Wrap your application with `DatadogProvider` close to the root. E.g.,
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { DatadogProvider } from '@servicetitan/datadog-rum';
|
|
56
|
+
|
|
57
|
+
const Root = () =>
|
|
58
|
+
return (
|
|
59
|
+
<DatadogProvider isEnabled={isEnabled} user={user}>
|
|
60
|
+
...
|
|
61
|
+
</DatadogProvider>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If your application uses hash-based routing, `DatadogProvider` should be placed inside `HashRouter`. E.g.,
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { HashRouter } from 'react-router-dom';
|
|
70
|
+
import { DatadogProvider } from '@servicetitan/datadog-rum';
|
|
71
|
+
|
|
72
|
+
const Root = () => {
|
|
73
|
+
return (
|
|
74
|
+
<HashRouter>
|
|
75
|
+
<DatadogProvider isEnabled={isEnabled} user={user} options={{ hashRouting: true }}>
|
|
76
|
+
...
|
|
77
|
+
</DatadogProvider>
|
|
78
|
+
</HashRouter>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Parameters
|
|
84
|
+
|
|
85
|
+
| Name | Type | Description |
|
|
86
|
+
| :---------- | :-------- | :------------------------------------------ |
|
|
87
|
+
| `isEnabled` | `boolean` | Enables DD RUM instrumentation |
|
|
88
|
+
| `user` | `User` | (optional) User session information |
|
|
89
|
+
| `options` | `Options` | (optional) Additional configuration options |
|
|
90
|
+
|
|
91
|
+
#### `User`
|
|
92
|
+
|
|
93
|
+
| Name | Type | Description |
|
|
94
|
+
| :-------------- | :----------------------------- | :----------------------------------- |
|
|
95
|
+
| `id` | `string` | User ID |
|
|
96
|
+
| `[key: string]` | `string \| number \| string[]` | (optional) Arbitrary user attributes |
|
|
97
|
+
|
|
98
|
+
#### `Options`
|
|
99
|
+
|
|
100
|
+
| Name | Type | Description |
|
|
101
|
+
| :------------ | :-------- | :------------------------------------------ |
|
|
102
|
+
| `hashRouting` | `boolean` | Sanitizes view names for hash-based routing |
|
|
103
|
+
|
|
104
|
+
## `beforeSend`
|
|
105
|
+
|
|
106
|
+
`beforeSend` is a callback function for enriching RUM events. Supported functionality:
|
|
107
|
+
|
|
108
|
+
- Adds MFE name and version for error and resource events coming from MFEs (`@error.service`, `@resource.service`, `@error.version`, and `@resource.version`)
|
|
109
|
+
- Adds Cloudflare Ray ID for resource events (`@resource.cfRay`)
|
|
110
|
+
|
|
111
|
+
### Usage
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { beforeSend } from '@servicetitan/datadog-rum';
|
|
115
|
+
import { datadogRum } from '@datadog/browser-rum';
|
|
116
|
+
|
|
117
|
+
const isEnabled = /.*go\d*\.servicetitan\.com/.test(window.location.hostname);
|
|
118
|
+
|
|
119
|
+
if (isEnabled) {
|
|
120
|
+
datadogRum.init({
|
|
121
|
+
applicationId: '<APPLICATION_ID>',
|
|
122
|
+
clientToken: '<CLIENT_TOKEN>',
|
|
123
|
+
site: 'datadoghq.com',
|
|
124
|
+
service: '<SERVICE_NAME>',
|
|
125
|
+
env: '<ENV_NAME>',
|
|
126
|
+
version: '<APPLICATION_VERSION>',
|
|
127
|
+
sessionSampleRate: 100,
|
|
128
|
+
sessionReplaySampleRate: 0,
|
|
129
|
+
defaultPrivacyLevel: 'mask-user-input',
|
|
130
|
+
beforeSend: beforeSend(), // <--beforeSend() returns handler that enriches events
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
```
|
package/docs/startup/review.mdx
CHANGED
|
@@ -192,6 +192,32 @@ npm pkg set "main"="dist/index.js" -w packages/lib
|
|
|
192
192
|
|
|
193
193
|
---
|
|
194
194
|
|
|
195
|
+
### require-all-react-dependencies
|
|
196
|
+
|
|
197
|
+
Ensures that any package which depends on either `react` or `react-dom` explicitly lists both as dependencies.
|
|
198
|
+
React and ReactDOM are tightly coupled and should always be paired together to avoid runtime issues.
|
|
199
|
+
|
|
200
|
+
#### ✅ Autofix
|
|
201
|
+
|
|
202
|
+
This rule supports autofix.
|
|
203
|
+
It adds the missing `react` or `react-dom` dependency, using the same version that is already present. For example, given:
|
|
204
|
+
|
|
205
|
+
```json title="package.json"
|
|
206
|
+
{
|
|
207
|
+
"dependencies": {
|
|
208
|
+
"react": "^18.3.1"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
It runs:
|
|
214
|
+
|
|
215
|
+
```sh
|
|
216
|
+
npm pkg set dependencies["react-dom"]="^18.3.1"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
195
221
|
### require-explicit-side-effects
|
|
196
222
|
|
|
197
223
|
Warns if a package is missing the `sideEffects` property in its `package.json`.
|
|
@@ -290,6 +316,22 @@ It sets the version of each dependency to the [highest](#highest-versions) of th
|
|
|
290
316
|
|
|
291
317
|
---
|
|
292
318
|
|
|
319
|
+
### require-one-react-version
|
|
320
|
+
|
|
321
|
+
Ensures the same version of `react` and `react-dom` is used across the workspace.
|
|
322
|
+
|
|
323
|
+
These two packages are fundamentally designed to work together, with `react-dom` relying heavily on the internal structures and mechanisms exposed by `react`.
|
|
324
|
+
|
|
325
|
+
While React 17 introduced features for gradual upgrades and potentially using multiple React versions in specific scenarios, maintaining synchronized versions of `react` and `react-dom` is the recommended and safest practice to ensure compatibility and avoid unforeseen issues.
|
|
326
|
+
|
|
327
|
+
#### ✅ Autofix
|
|
328
|
+
|
|
329
|
+
This rule supports autofix.
|
|
330
|
+
It sets `react` and `react-dom` to the most common version in the repo.
|
|
331
|
+
If multiple versions tie for the most common, it uses the [highest](#highest-versions) version among the top contenders.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
293
335
|
### require-one-uikit-version
|
|
294
336
|
|
|
295
337
|
Ensures the same version of related `uikit` packages is installed across the workspace.
|
package/docs/startup/test.mdx
CHANGED
|
@@ -2,10 +2,204 @@
|
|
|
2
2
|
title: test
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Runs
|
|
5
|
+
Runs your project's tests.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Supports both Jest and Vitest.
|
|
8
|
+
- Automatically selects the test runner based on your workspace configuration or the `--runner` option.
|
|
9
|
+
- Handles runner-specific arguments and passes them through to the underlying test tool.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Run all tests with Jest (default):
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx startup test
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Run all tests with Vitest:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npx startup test --runner vitest
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
:::tip
|
|
26
|
+
Use the double-dash (--) separator to pass arguments to an `npm` script.
|
|
27
|
+
This separator indicates that any arguments following it should be passed directly to the script being executed, rather than being interpreted by `npm` itself.
|
|
28
|
+
For example, given the standard `startup test` script:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"test": "npx startup test"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Running,
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npm run test -- --runner vitest
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Executes,
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npx startup test --runner vitest
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
:::
|
|
49
|
+
|
|
50
|
+
## Running Specific Tests
|
|
51
|
+
|
|
52
|
+
To run specific tests, pass their file names or paths as additional arguments.
|
|
53
|
+
This works just like running Jest and Vitest directly, simply specify the file(s) you want to test:
|
|
54
|
+
|
|
55
|
+
### Examples
|
|
56
|
+
|
|
57
|
+
Run a specific test with Jest (default):
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npx startup test app.test.tsx
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Run a specific test with Vitest:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
npx startup test --runner vitest app.test.tsx
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Using Jest
|
|
70
|
+
|
|
71
|
+
The `startup test` command uses the Jest test runner by default.
|
|
72
|
+
|
|
73
|
+
### Configuration
|
|
74
|
+
|
|
75
|
+
The Jest runner provides a default, built-in configuration optimized for ServiceTitan workspaces.
|
|
76
|
+
|
|
77
|
+
You can override the defaults by specifying [Jest options](https://jestjs.io/docs/configuration) in your workspace `package.json` under the `"cli.jest"` key (the `"cli.test"` key also works, for backward compatibility). You can also use a standard Jest config file (such as `jest.config.js`) to override defaults.
|
|
78
|
+
|
|
79
|
+
Any options passed directly via the command line (e.g., `npx startup test --coverage`) take the highest precedence.
|
|
80
|
+
|
|
81
|
+
:::caution
|
|
82
|
+
If your project includes a standard Jest config file and also specifies Jest options in the workspace `package.json`, ensure that the configurations are mutually exclusive.
|
|
83
|
+
To avoid confusing or unexpected behavior, do not specify the same setting in both locations.
|
|
84
|
+
:::
|
|
85
|
+
|
|
86
|
+
### Examples
|
|
87
|
+
|
|
88
|
+
Use the workspace `package.json` to set up code that runs before each test file is executed:
|
|
89
|
+
|
|
90
|
+
```json title="package.json"
|
|
91
|
+
{
|
|
92
|
+
"cli": {
|
|
93
|
+
"jest": {
|
|
94
|
+
"setupFilesAfterEnv": ["<rootDir>/jest.setup.ts"]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
:::note
|
|
101
|
+
For backward compatibility, you may also use the `ci.test` key:
|
|
102
|
+
:::
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
Use `jest.config.js` to increase Jest's `testTimeout` on Windows:
|
|
107
|
+
|
|
108
|
+
```js title="jest.config.js"
|
|
109
|
+
module.exports = {
|
|
110
|
+
testTimeout: process.platform === 'win32' ? 60 * 1000 : undefined, // increase timeout on Windows
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
Use the command line to collect test coverage:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
npx startup test --coverage
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use the command line to enable Jest's watch mode:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npx startup test --watch
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Using Vitest
|
|
129
|
+
|
|
130
|
+
✨ New in **v31.6.0** ✨
|
|
131
|
+
|
|
132
|
+
You can change the default test runner to `vitest` in your workspace's `package.json`:
|
|
133
|
+
|
|
134
|
+
```json title="package.json"
|
|
135
|
+
{
|
|
136
|
+
"cli": {
|
|
137
|
+
"testRunner": "vitest"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Or override it per invocation with the `--runner` option.
|
|
143
|
+
|
|
144
|
+
### Configuration
|
|
145
|
+
|
|
146
|
+
The Vitest runner uses a layered configuration approach to provide sensible defaults while allowing full customization.
|
|
147
|
+
|
|
148
|
+
- Uses the default, built-in configuration as a base.
|
|
149
|
+
- Applies workspace overrides from `package.json`.
|
|
150
|
+
- Applies overrides from your Vitest config file.
|
|
151
|
+
- Applies command line options last.
|
|
152
|
+
|
|
153
|
+
1. **Default Configuration:**
|
|
154
|
+
The runner starts with a built-in default configuration optimized for ServiceTitan workspaces. This includes sensible coverage settings, the environment (`jsdom`), file exclusions, and more.
|
|
155
|
+
|
|
156
|
+
2. **Workspace Configuration:**
|
|
157
|
+
You can override defaults by specifying [Vitest options](https://vitest.dev/config) in your workspace `package.json` under the `"cli.vitest"` key.
|
|
158
|
+
|
|
159
|
+
3. **Vitest Config File:**
|
|
160
|
+
If your project includes a standard Vitest config file (such as `vitest.config.ts` or `vite.config.ts`), its settings will override both the defaults and workspace configuration.
|
|
161
|
+
|
|
162
|
+
4. **Command Line Arguments:**
|
|
163
|
+
Any options passed directly via the command line (e.g., `npx startup test --runner vitest --coverage`) take highest precedence and override all previous configuration layers.
|
|
164
|
+
|
|
165
|
+
### Examples
|
|
166
|
+
|
|
167
|
+
Use workspace `package.json` to make `vitest` APIs available [globally](https://vitest.dev/config/#globals) like Jest:
|
|
168
|
+
|
|
169
|
+
```json title="package.json"
|
|
170
|
+
{
|
|
171
|
+
"cli": {
|
|
172
|
+
"vitest": {
|
|
173
|
+
"globals": true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
Use Vitest config file to disable watch mode:
|
|
182
|
+
|
|
183
|
+
```ts title="vitest.config.mts"
|
|
184
|
+
import { defineConfig } from 'vitest/config';
|
|
185
|
+
|
|
186
|
+
export default defineConfig({
|
|
187
|
+
test: {
|
|
188
|
+
watch: false,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
Use the command line to disable watch mode:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
npx startup test --runner vitest --run
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Use the command line to collect code coverage:
|
|
8
202
|
|
|
9
203
|
```sh
|
|
10
|
-
npx startup test --
|
|
204
|
+
npx startup test --runner vitest --coverage
|
|
11
205
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/docs-uikit",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,5 +16,5 @@
|
|
|
16
16
|
"cli": {
|
|
17
17
|
"webpack": false
|
|
18
18
|
},
|
|
19
|
-
"gitHead": "
|
|
19
|
+
"gitHead": "533bcbd267e11c88700b29f539ca1cb5de6440ae"
|
|
20
20
|
}
|