exisjs 0.7.12 → 0.7.13
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/README.md +195 -39
- package/dist/config/types.d.ts +2 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/decorators/params.d.ts +21 -0
- package/dist/decorators/params.d.ts.map +1 -1
- package/dist/decorators/params.js +21 -1
- package/dist/decorators/params.js.map +1 -1
- package/dist/di/container.d.ts +15 -6
- package/dist/di/container.d.ts.map +1 -1
- package/dist/di/container.js +26 -3
- package/dist/di/container.js.map +1 -1
- package/dist/di/index.d.ts +1 -1
- package/dist/di/index.d.ts.map +1 -1
- package/dist/di/index.js.map +1 -1
- package/dist/di/inject.d.ts +2 -1
- package/dist/di/inject.d.ts.map +1 -1
- package/dist/di/inject.js +2 -1
- package/dist/di/inject.js.map +1 -1
- package/dist/docs/BENCHMARKS.md +4 -4
- package/dist/docs/content/README.md +43 -44
- package/dist/docs/content/boundaries.mdx +138 -61
- package/dist/docs/content/cli/commands.mdx +151 -128
- package/dist/docs/content/cli/overview.mdx +61 -47
- package/dist/docs/content/cli/usage.mdx +107 -30
- package/dist/docs/content/config.mdx +145 -158
- package/dist/docs/content/controllers.mdx +193 -464
- package/dist/docs/content/cron.mdx +183 -69
- package/dist/docs/content/decorators.mdx +449 -154
- package/dist/docs/content/errors.mdx +202 -305
- package/dist/docs/content/exisjs-mcp.mdx +59 -49
- package/dist/docs/content/installation.mdx +243 -157
- package/dist/docs/content/introduction.mdx +220 -48
- package/dist/docs/content/middleware.mdx +171 -497
- package/dist/docs/content/modules.mdx +141 -83
- package/dist/docs/content/providers.mdx +216 -180
- package/dist/docs/content/requests.mdx +168 -488
- package/dist/docs/content/responses.mdx +200 -533
- package/dist/docs/content/routing.mdx +235 -598
- package/dist/docs/content/security.mdx +233 -57
- package/dist/docs/content/structure.mdx +151 -240
- package/dist/docs/content/swagger.mdx +192 -91
- package/dist/docs/content/testing.mdx +205 -74
- package/dist/docs/content/validation.mdx +479 -341
- package/dist/docs/reference/README.md +34 -2
- package/dist/docs/reference/config.mdx +277 -75
- package/dist/docs/reference/context.mdx +197 -106
- package/dist/docs/reference/cron.mdx +266 -152
- package/dist/docs/reference/database.mdx +135 -53
- package/dist/docs/reference/decorators.mdx +234 -116
- package/dist/docs/reference/di.mdx +146 -112
- package/dist/docs/reference/error.mdx +155 -178
- package/dist/docs/reference/exis.mdx +141 -70
- package/dist/docs/reference/logger.mdx +110 -126
- package/dist/docs/reference/middleware.mdx +235 -158
- package/dist/docs/reference/plugin.mdx +136 -64
- package/dist/docs/reference/router.mdx +275 -293
- package/dist/docs/reference/sanitize.mdx +91 -87
- package/dist/docs/reference/swagger.mdx +280 -100
- package/dist/docs/reference/testing.mdx +223 -89
- package/dist/docs/reference/validator.mdx +194 -206
- package/dist/lib/start-server.js +3 -8
- package/dist/lib/start-server.js.map +1 -1
- package/dist/module/module.d.ts +6 -3
- package/dist/module/module.d.ts.map +1 -1
- package/dist/module/module.js +17 -3
- package/dist/module/module.js.map +1 -1
- package/dist/router/controller-registrar.d.ts.map +1 -1
- package/dist/router/controller-registrar.js +26 -4
- package/dist/router/controller-registrar.js.map +1 -1
- package/dist/server/app.d.ts +3 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +24 -8
- package/dist/server/app.js.map +1 -1
- package/dist/server/request.d.ts +2 -0
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +11 -0
- package/dist/server/request.js.map +1 -1
- package/dist/swagger/generator.d.ts.map +1 -1
- package/dist/swagger/generator.js +130 -10
- package/dist/swagger/generator.js.map +1 -1
- package/dist/telemetry/index.d.ts +12 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +121 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/testing/client.d.ts +1 -0
- package/dist/testing/client.d.ts.map +1 -1
- package/dist/testing/client.js +4 -1
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +11 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/validator/builder.d.ts +26 -1
- package/dist/validator/builder.d.ts.map +1 -1
- package/dist/validator/builder.js +31 -0
- package/dist/validator/builder.js.map +1 -1
- package/dist/validator/engine.d.ts +23 -0
- package/dist/validator/engine.d.ts.map +1 -1
- package/dist/validator/engine.js +228 -31
- package/dist/validator/engine.js.map +1 -1
- package/dist/validator/index.d.ts +8 -4
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +4 -1
- package/dist/validator/index.js.map +1 -1
- package/dist/validator/tex-types.d.ts +15 -0
- package/dist/validator/tex-types.d.ts.map +1 -1
- package/dist/validator/tex-types.js +102 -0
- package/dist/validator/tex-types.js.map +1 -1
- package/dist/validator/tex.d.ts +1 -1
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js +3 -1
- package/dist/validator/tex.js.map +1 -1
- package/dist/validator/types.d.ts +1 -0
- package/dist/validator/types.d.ts.map +1 -1
- package/package.json +46 -14
- package/dist/docs/content/dataloader.mdx +0 -170
- package/dist/docs/reference/dataloader.mdx +0 -91
|
@@ -1,145 +1,279 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
description: "
|
|
2
|
+
title: "exisjs/testing"
|
|
3
|
+
description: "API Reference for ExisJS testing framework: test runner, createTestApp, HTTP assertions, matchers (expect), mocks (ex), and unit mocks."
|
|
4
|
+
nextUrl: "/docs/reference/plugin"
|
|
5
|
+
nextTitle: "Plugin Reference"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
|
-
#
|
|
8
|
+
# `exisjs/testing`
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
The `exisjs/testing` module provides an integrated testing framework built on Node's native runner (`node:test`) and assertion engine (`node:assert`). It includes the `createTestApp` synthetic HTTP client, fluent `expect` assertions, Jest-compatible `ex` spies/mocks, and unit-level mock factories (`createMockRequest`, `createMockResponse`).
|
|
9
11
|
|
|
10
12
|
---
|
|
11
13
|
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
ExisJS fully re-exports the native `node:test` runner methods, ensuring maximum IDE compatibility while providing powerful internal enhancements (like `.each()`).
|
|
14
|
+
## Module Exports
|
|
15
15
|
|
|
16
16
|
```typescript
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import {
|
|
18
|
+
// Test Runner & Lifecycle
|
|
19
|
+
test,
|
|
20
|
+
describe,
|
|
21
|
+
it,
|
|
22
|
+
before,
|
|
23
|
+
beforeAll,
|
|
24
|
+
after,
|
|
25
|
+
afterAll,
|
|
26
|
+
beforeEach,
|
|
27
|
+
afterEach,
|
|
28
|
+
registerCleanup,
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
// Assertions & Matchers
|
|
31
|
+
expect,
|
|
22
32
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export function afterEach(fn: HookFunction): void
|
|
27
|
-
```
|
|
33
|
+
// Mocks, Spies & Timers
|
|
34
|
+
ex,
|
|
35
|
+
mock,
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
// HTTP Integration Testing Client
|
|
38
|
+
createTestApp,
|
|
39
|
+
TestRequest,
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
// Unit Mocking Helpers
|
|
42
|
+
createMockRequest,
|
|
43
|
+
createMockResponse,
|
|
44
|
+
createMockLogger,
|
|
45
|
+
createMockNext,
|
|
46
|
+
getResponseBody,
|
|
47
|
+
getResponseHeader,
|
|
48
|
+
} from 'exisjs/testing'
|
|
49
|
+
|
|
50
|
+
import type {
|
|
51
|
+
TestApp,
|
|
52
|
+
TestRequest,
|
|
53
|
+
TestResponse,
|
|
54
|
+
TestOptions,
|
|
55
|
+
TestContext,
|
|
56
|
+
TestFunction,
|
|
57
|
+
HookFunction,
|
|
58
|
+
MockRequestOptions,
|
|
59
|
+
MockResponse,
|
|
60
|
+
} from 'exisjs/testing'
|
|
39
61
|
```
|
|
40
62
|
|
|
41
63
|
---
|
|
42
64
|
|
|
43
|
-
##
|
|
65
|
+
## 1. Native Test Runner API
|
|
44
66
|
|
|
45
|
-
|
|
46
|
-
Automatically handles booting an ExisJS `App`, processing its startup hooks, and safely closing all database and worker connections. Returns a `TestApp` client for performing HTTP requests.
|
|
67
|
+
ExisJS enhances the native Node test runner with Jest-like `.each()` parameterization and typed test hooks.
|
|
47
68
|
|
|
48
69
|
```typescript
|
|
49
|
-
|
|
70
|
+
// Test suites and cases
|
|
71
|
+
describe(name: string, fn?: TestFunction): void
|
|
72
|
+
test(name: string, fn?: TestFunction): void
|
|
73
|
+
test(name: string, options: TestOptions, fn?: TestFunction): void
|
|
74
|
+
it(name: string, fn?: TestFunction): void
|
|
75
|
+
|
|
76
|
+
// Modifiers
|
|
77
|
+
test.only(name: string, fn?: TestFunction): void
|
|
78
|
+
test.skip(name: string, fn?: TestFunction): void
|
|
79
|
+
test.todo(name: string, fn?: TestFunction): void
|
|
80
|
+
|
|
81
|
+
// Lifecycle hooks
|
|
82
|
+
before(fn: HookFunction): void
|
|
83
|
+
beforeEach(fn: HookFunction): void
|
|
84
|
+
after(fn: HookFunction): void
|
|
85
|
+
afterEach(fn: HookFunction): void
|
|
50
86
|
```
|
|
51
87
|
|
|
52
|
-
### `
|
|
53
|
-
Allows third-party plugins or custom test setups to register a global cleanup function that will be executed when the test runner terminates.
|
|
88
|
+
### Parametrized Tests (`.each`)
|
|
54
89
|
|
|
55
90
|
```typescript
|
|
56
|
-
|
|
91
|
+
test.each([
|
|
92
|
+
[1, 2, 3],
|
|
93
|
+
[10, 20, 30],
|
|
94
|
+
[-5, 5, 0],
|
|
95
|
+
])('calculates %d + %d = %d', (a, b, expected) => {
|
|
96
|
+
expect(a + b).toBe(expected)
|
|
97
|
+
})
|
|
57
98
|
```
|
|
58
99
|
|
|
59
100
|
---
|
|
60
101
|
|
|
61
|
-
## HTTP
|
|
102
|
+
## 2. HTTP Integration Testing (`createTestApp`)
|
|
62
103
|
|
|
63
|
-
|
|
104
|
+
Instantiates an in-memory HTTP test client that dispatches synthetic requests into an ExisJS `App` instance without binding a network port.
|
|
64
105
|
|
|
65
|
-
### `TestApp`
|
|
66
106
|
```typescript
|
|
67
|
-
|
|
68
|
-
get(path: string): TestRequest
|
|
69
|
-
post(path: string): TestRequest
|
|
70
|
-
put(path: string): TestRequest
|
|
71
|
-
patch(path: string): TestRequest
|
|
72
|
-
delete(path: string): TestRequest
|
|
73
|
-
options(path: string): TestRequest
|
|
74
|
-
head(path: string): TestRequest
|
|
75
|
-
request(method: string, path: string): TestRequest
|
|
76
|
-
}
|
|
107
|
+
function createTestApp(app: App | ExisAppDefinition | ExisConfig): TestApp
|
|
77
108
|
```
|
|
78
109
|
|
|
79
|
-
### `
|
|
80
|
-
|
|
110
|
+
### `TestApp` Interface
|
|
111
|
+
|
|
112
|
+
| Method | Signature | Description |
|
|
113
|
+
| :--- | :--- | :--- |
|
|
114
|
+
| `get` | `(path: string, options?: RequestOptions): TestRequest` | Initiates a synthetic `GET` request. |
|
|
115
|
+
| `post` | `(path: string, options?: RequestOptions \| unknown): TestRequest` | Initiates a synthetic `POST` request. |
|
|
116
|
+
| `put` | `(path: string, options?: RequestOptions \| unknown): TestRequest` | Initiates a synthetic `PUT` request. |
|
|
117
|
+
| `patch` | `(path: string, options?: RequestOptions \| unknown): TestRequest` | Initiates a synthetic `PATCH` request. |
|
|
118
|
+
| `delete` | `(path: string, options?: RequestOptions): TestRequest` | Initiates a synthetic `DELETE` request. |
|
|
119
|
+
| `options` | `(path: string, options?: RequestOptions): TestRequest` | Initiates an `OPTIONS` preflight request. |
|
|
120
|
+
| `head` | `(path: string, options?: RequestOptions): TestRequest` | Initiates a `HEAD` request. |
|
|
121
|
+
| `request` | `(method: string, path: string, options?: RequestOptions): TestRequest` | Dispatches an arbitrary HTTP method request. |
|
|
122
|
+
|
|
123
|
+
### `TestRequest` Builder
|
|
124
|
+
|
|
125
|
+
Fluent request builder allowing header configuration, payload attachment, and response assertions:
|
|
81
126
|
|
|
82
127
|
```typescript
|
|
83
|
-
class TestRequest {
|
|
128
|
+
class TestRequest implements PromiseLike<TestResponse> {
|
|
84
129
|
send(body: unknown): this
|
|
85
130
|
set(header: string, value: string): this
|
|
86
|
-
|
|
87
|
-
// Assertions
|
|
88
131
|
expect(status: number): this
|
|
89
132
|
expect(header: string, value: string | RegExp): this
|
|
90
133
|
expect(body: unknown): this
|
|
91
|
-
|
|
92
|
-
// Execution
|
|
93
134
|
execute(): Promise<TestResponse>
|
|
94
|
-
then<T>(onfulfilled: (res: TestResponse) => T): Promise<T>
|
|
95
135
|
}
|
|
96
136
|
```
|
|
97
137
|
|
|
98
|
-
### `TestResponse`
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
138
|
+
### `TestResponse` Interface
|
|
139
|
+
|
|
140
|
+
| Property | Type | Description |
|
|
141
|
+
| :--- | :--- | :--- |
|
|
142
|
+
| `status` | `number` | HTTP status code returned by the route handler. |
|
|
143
|
+
| `headers` | `http.IncomingHttpHeaders` | Dictionary of HTTP response headers. |
|
|
144
|
+
| `body` | `any` | Parsed JSON response payload (or undefined if not JSON). |
|
|
145
|
+
| `text` | `string` | Raw UTF-8 string content of the response payload. |
|
|
146
|
+
|
|
147
|
+
### Integration Test Example
|
|
148
|
+
|
|
149
|
+
```typescript filename="tests/users.test.ts"
|
|
150
|
+
import { describe, it, expect, createTestApp } from 'exisjs/testing'
|
|
151
|
+
import server from '../src/http/server'
|
|
152
|
+
|
|
153
|
+
describe('Users API', () => {
|
|
154
|
+
const client = createTestApp(server)
|
|
155
|
+
|
|
156
|
+
it('creates and returns a user payload', async () => {
|
|
157
|
+
const res = await client
|
|
158
|
+
.post('/users', { name: 'Alice', email: 'alice@example.com' })
|
|
159
|
+
.set('Authorization', 'Bearer token_123')
|
|
160
|
+
.expect(201)
|
|
161
|
+
.expect('content-type', /application\/json/)
|
|
162
|
+
|
|
163
|
+
expect(res.body).toMatchObject({
|
|
164
|
+
success: true,
|
|
165
|
+
data: {
|
|
166
|
+
name: 'Alice',
|
|
167
|
+
email: 'alice@example.com',
|
|
168
|
+
},
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
})
|
|
106
172
|
```
|
|
107
173
|
|
|
108
174
|
---
|
|
109
175
|
|
|
110
|
-
##
|
|
176
|
+
## 3. Assertion Engine (`expect`)
|
|
111
177
|
|
|
112
|
-
The `
|
|
178
|
+
The `expect(actual)` function returns a rich matcher engine with negative chaining via `.not`:
|
|
179
|
+
|
|
180
|
+
### Equality & Truthiness
|
|
181
|
+
|
|
182
|
+
| Matcher | Description |
|
|
183
|
+
| :--- | :--- |
|
|
184
|
+
| `toBe(value)` | Strict referential equality (`===`). |
|
|
185
|
+
| `toEqual(value)` | Deep equality check across objects and arrays. |
|
|
186
|
+
| `toStrictEqual(value)` | Deep strict equality checking prototypes and `undefined` keys. |
|
|
187
|
+
| `toMatchObject(subset)` | Verifies that the target object contains the specified subset of properties. |
|
|
188
|
+
| `toBeTruthy()` | Asserts truthy value. |
|
|
189
|
+
| `toBeFalsy()` | Asserts falsy value. |
|
|
190
|
+
| `toBeNull()` | Asserts `null`. |
|
|
191
|
+
| `toBeUndefined()` | Asserts `undefined`. |
|
|
192
|
+
| `toBeDefined()` | Asserts not `undefined`. |
|
|
193
|
+
|
|
194
|
+
### Numeric Matchers
|
|
195
|
+
|
|
196
|
+
| Matcher | Description |
|
|
197
|
+
| :--- | :--- |
|
|
198
|
+
| `toBeGreaterThan(n)` | Asserts `actual > n`. |
|
|
199
|
+
| `toBeGreaterThanOrEqual(n)` | Asserts `actual >= n`. |
|
|
200
|
+
| `toBeLessThan(n)` | Asserts `actual < n`. |
|
|
201
|
+
| `toBeLessThanOrEqual(n)` | Asserts `actual <= n`. |
|
|
202
|
+
| `toBeCloseTo(n, precision?)` | Asserts floating point approximation. |
|
|
203
|
+
|
|
204
|
+
### Strings, Arrays & Errors
|
|
205
|
+
|
|
206
|
+
| Matcher | Description |
|
|
207
|
+
| :--- | :--- |
|
|
208
|
+
| `toContain(item)` | Checks if a string contains a substring or array contains an element. |
|
|
209
|
+
| `toMatch(regex)` | Asserts string matches regular expression. |
|
|
210
|
+
| `toHaveLength(length)` | Asserts `.length` property matches. |
|
|
211
|
+
| `toThrow(error?)` | Asserts that a function throws an error matching the predicate. |
|
|
212
|
+
| `toBeInstanceOf(constructor)` | Asserts `actual instanceof constructor`. |
|
|
213
|
+
|
|
214
|
+
### Mock Assertions
|
|
215
|
+
|
|
216
|
+
| Matcher | Description |
|
|
217
|
+
| :--- | :--- |
|
|
218
|
+
| `toHaveBeenCalled()` | Asserts the mock was called at least once. |
|
|
219
|
+
| `toHaveBeenCalledTimes(count)` | Asserts the mock was invoked an exact number of times. |
|
|
220
|
+
| `toHaveBeenCalledWith(...args)` | Asserts the mock was called with matching arguments. |
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 4. Spies, Mocks & Timers (`ex`)
|
|
225
|
+
|
|
226
|
+
Jest-compatible API wrapping Node's native mocking subsystem:
|
|
113
227
|
|
|
114
228
|
```typescript
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
229
|
+
// Function & Method Spies
|
|
230
|
+
const fn = ex.fn((x: number) => x * 2)
|
|
231
|
+
const spy = ex.spyOn(userService, 'findById')
|
|
232
|
+
|
|
233
|
+
// Mock Implementations
|
|
234
|
+
fn.mockReturnValue(42)
|
|
235
|
+
fn.mockResolvedValue({ id: '1' })
|
|
236
|
+
fn.mockRejectedValue(new Error('Failed'))
|
|
237
|
+
fn.mockImplementation((name) => `Hello ${name}`)
|
|
238
|
+
fn.mockClear()
|
|
239
|
+
fn.mockRestore()
|
|
240
|
+
|
|
241
|
+
// Timer Manipulation
|
|
242
|
+
ex.setSystemTime(new Date('2026-01-01T00:00:00Z'))
|
|
243
|
+
ex.advanceTimersByTime(5000)
|
|
244
|
+
|
|
245
|
+
// Module Mocking
|
|
246
|
+
ex.mock('./mail-client', () => ({
|
|
247
|
+
sendMail: ex.fn().mockResolvedValue(true),
|
|
248
|
+
}))
|
|
131
249
|
```
|
|
132
250
|
|
|
133
|
-
|
|
134
|
-
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 5. Unit-Level Mocking Helpers
|
|
254
|
+
|
|
255
|
+
For unit testing individual middleware, guards, or filters without booting an entire server:
|
|
135
256
|
|
|
136
257
|
```typescript
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
258
|
+
import {
|
|
259
|
+
createMockRequest,
|
|
260
|
+
createMockResponse,
|
|
261
|
+
createMockNext,
|
|
262
|
+
getResponseBody,
|
|
263
|
+
getResponseHeader,
|
|
264
|
+
} from 'exisjs/testing'
|
|
265
|
+
|
|
266
|
+
const req = createMockRequest({
|
|
267
|
+
method: 'POST',
|
|
268
|
+
url: '/api/v1/checkout',
|
|
269
|
+
headers: { 'x-tenant-id': 'tenant_123' },
|
|
270
|
+
body: { amount: 5000 },
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
const res = createMockResponse()
|
|
274
|
+
const next = createMockNext()
|
|
275
|
+
|
|
276
|
+
await authGuard(req, res, next)
|
|
277
|
+
|
|
278
|
+
expect(next.called).toBe(true)
|
|
145
279
|
```
|