@xivdyetools/test-utils 1.0.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/LICENSE +37 -0
- package/README.md +144 -0
- package/dist/assertions/index.d.ts +7 -0
- package/dist/assertions/index.d.ts.map +1 -0
- package/dist/assertions/index.js +7 -0
- package/dist/assertions/index.js.map +1 -0
- package/dist/assertions/response.d.ts +84 -0
- package/dist/assertions/response.d.ts.map +1 -0
- package/dist/assertions/response.js +125 -0
- package/dist/assertions/response.js.map +1 -0
- package/dist/auth/context.d.ts +55 -0
- package/dist/auth/context.d.ts.map +1 -0
- package/dist/auth/context.js +95 -0
- package/dist/auth/context.js.map +1 -0
- package/dist/auth/headers.d.ts +64 -0
- package/dist/auth/headers.d.ts.map +1 -0
- package/dist/auth/headers.js +101 -0
- package/dist/auth/headers.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +10 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/jwt.d.ts +76 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +77 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/signature.d.ts +64 -0
- package/dist/auth/signature.d.ts.map +1 -0
- package/dist/auth/signature.js +75 -0
- package/dist/auth/signature.js.map +1 -0
- package/dist/cloudflare/analytics.d.ts +55 -0
- package/dist/cloudflare/analytics.d.ts.map +1 -0
- package/dist/cloudflare/analytics.js +44 -0
- package/dist/cloudflare/analytics.js.map +1 -0
- package/dist/cloudflare/d1.d.ts +101 -0
- package/dist/cloudflare/d1.d.ts.map +1 -0
- package/dist/cloudflare/d1.js +148 -0
- package/dist/cloudflare/d1.js.map +1 -0
- package/dist/cloudflare/fetcher.d.ts +72 -0
- package/dist/cloudflare/fetcher.d.ts.map +1 -0
- package/dist/cloudflare/fetcher.js +136 -0
- package/dist/cloudflare/fetcher.js.map +1 -0
- package/dist/cloudflare/index.d.ts +12 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +12 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/cloudflare/kv.d.ts +85 -0
- package/dist/cloudflare/kv.d.ts.map +1 -0
- package/dist/cloudflare/kv.js +138 -0
- package/dist/cloudflare/kv.js.map +1 -0
- package/dist/cloudflare/r2.d.ts +88 -0
- package/dist/cloudflare/r2.d.ts.map +1 -0
- package/dist/cloudflare/r2.js +127 -0
- package/dist/cloudflare/r2.js.map +1 -0
- package/dist/constants/index.d.ts +8 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +8 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/pkce.d.ts +89 -0
- package/dist/constants/pkce.d.ts.map +1 -0
- package/dist/constants/pkce.js +107 -0
- package/dist/constants/pkce.js.map +1 -0
- package/dist/constants/secrets.d.ts +72 -0
- package/dist/constants/secrets.d.ts.map +1 -0
- package/dist/constants/secrets.js +73 -0
- package/dist/constants/secrets.js.map +1 -0
- package/dist/dom/canvas.d.ts +108 -0
- package/dist/dom/canvas.d.ts.map +1 -0
- package/dist/dom/canvas.js +125 -0
- package/dist/dom/canvas.js.map +1 -0
- package/dist/dom/fetch.d.ts +69 -0
- package/dist/dom/fetch.d.ts.map +1 -0
- package/dist/dom/fetch.js +107 -0
- package/dist/dom/fetch.js.map +1 -0
- package/dist/dom/index.d.ts +12 -0
- package/dist/dom/index.d.ts.map +1 -0
- package/dist/dom/index.js +12 -0
- package/dist/dom/index.js.map +1 -0
- package/dist/dom/localStorage.d.ts +80 -0
- package/dist/dom/localStorage.d.ts.map +1 -0
- package/dist/dom/localStorage.js +124 -0
- package/dist/dom/localStorage.js.map +1 -0
- package/dist/dom/matchMedia.d.ts +51 -0
- package/dist/dom/matchMedia.d.ts.map +1 -0
- package/dist/dom/matchMedia.js +120 -0
- package/dist/dom/matchMedia.js.map +1 -0
- package/dist/dom/resizeObserver.d.ts +68 -0
- package/dist/dom/resizeObserver.d.ts.map +1 -0
- package/dist/dom/resizeObserver.js +99 -0
- package/dist/dom/resizeObserver.js.map +1 -0
- package/dist/factories/category.d.ts +74 -0
- package/dist/factories/category.d.ts.map +1 -0
- package/dist/factories/category.js +99 -0
- package/dist/factories/category.js.map +1 -0
- package/dist/factories/dye.d.ts +76 -0
- package/dist/factories/dye.d.ts.map +1 -0
- package/dist/factories/dye.js +211 -0
- package/dist/factories/dye.js.map +1 -0
- package/dist/factories/index.d.ts +13 -0
- package/dist/factories/index.d.ts.map +1 -0
- package/dist/factories/index.js +14 -0
- package/dist/factories/index.js.map +1 -0
- package/dist/factories/preset.d.ts +105 -0
- package/dist/factories/preset.d.ts.map +1 -0
- package/dist/factories/preset.js +170 -0
- package/dist/factories/preset.js.map +1 -0
- package/dist/factories/user.d.ts +74 -0
- package/dist/factories/user.d.ts.map +1 -0
- package/dist/factories/user.js +115 -0
- package/dist/factories/user.js.map +1 -0
- package/dist/factories/vote.d.ts +55 -0
- package/dist/factories/vote.d.ts.map +1 -0
- package/dist/factories/vote.js +68 -0
- package/dist/factories/vote.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/counters.d.ts +35 -0
- package/dist/utils/counters.d.ts.map +1 -0
- package/dist/utils/counters.js +53 -0
- package/dist/utils/counters.js.map +1 -0
- package/dist/utils/crypto.d.ts +42 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/crypto.js +72 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Flash Galatine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
FINAL FANTASY XIV © SQUARE ENIX CO., LTD. All Rights Reserved.
|
|
26
|
+
|
|
27
|
+
This project is a fan-made tool and is not affiliated with, endorsed by, or
|
|
28
|
+
sponsored by Square Enix Co., Ltd. FINAL FANTASY is a registered trademark
|
|
29
|
+
of Square Enix Holdings Co., Ltd.
|
|
30
|
+
|
|
31
|
+
Game data, including dye names, colors, and acquisition methods, are property
|
|
32
|
+
of Square Enix Co., Ltd. and are used under fair use for educational and
|
|
33
|
+
informational purposes only.
|
|
34
|
+
|
|
35
|
+
Market board data is provided by Universalis (https://universalis.app/),
|
|
36
|
+
an independent third-party service not affiliated with Square Enix.
|
|
37
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @xivdyetools/test-utils
|
|
2
|
+
|
|
3
|
+
Shared testing utilities for the xivdyetools ecosystem. Provides mocks for Cloudflare Workers bindings, authentication helpers, domain object factories, and DOM utilities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D @xivdyetools/test-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Cloudflare Workers Mocks**: D1Database, KVNamespace, R2Bucket, AnalyticsEngineDataset, Fetcher (Service Bindings)
|
|
14
|
+
- **Auth Helpers**: JWT creation/verification, HMAC signatures, auth context factories
|
|
15
|
+
- **Domain Factories**: Preset, Category, Vote, User mock data factories
|
|
16
|
+
- **DOM Utilities**: localStorage mock, Canvas mock, ResizeObserver mock
|
|
17
|
+
- **Assertions**: Response assertion helpers for API testing
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Cloudflare Mocks
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createMockD1Database, createMockKV, createMockFetcher } from '@xivdyetools/test-utils/cloudflare';
|
|
25
|
+
|
|
26
|
+
// D1 Database mock with query tracking
|
|
27
|
+
const db = createMockD1Database();
|
|
28
|
+
db._setupMock((query, bindings) => {
|
|
29
|
+
if (query.includes('SELECT')) return { id: 1, name: 'Test' };
|
|
30
|
+
return null;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Use in your tests
|
|
34
|
+
const env = { DB: db as unknown as D1Database };
|
|
35
|
+
|
|
36
|
+
// Check what queries were executed
|
|
37
|
+
console.log(db._queries); // ['SELECT ...']
|
|
38
|
+
console.log(db._bindings); // [['param1', 'param2']]
|
|
39
|
+
|
|
40
|
+
// Reset between tests
|
|
41
|
+
db._reset();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Auth Helpers
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { createTestJWT, createBotSignature, createAuthContext } from '@xivdyetools/test-utils/auth';
|
|
48
|
+
|
|
49
|
+
// Create a valid JWT for testing
|
|
50
|
+
const jwt = await createTestJWT('your-secret', {
|
|
51
|
+
sub: 'user-123',
|
|
52
|
+
username: 'TestUser',
|
|
53
|
+
global_name: 'Test User',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Create HMAC signature for bot auth
|
|
57
|
+
const signature = await createBotSignature(
|
|
58
|
+
timestamp,
|
|
59
|
+
'user-discord-id',
|
|
60
|
+
'username',
|
|
61
|
+
'signing-secret'
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Create auth context for middleware testing
|
|
65
|
+
const ctx = createAuthContext({ isModerator: true });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Domain Factories
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import {
|
|
72
|
+
createMockPreset,
|
|
73
|
+
createMockPresetRow,
|
|
74
|
+
createMockSubmission,
|
|
75
|
+
createMockUser,
|
|
76
|
+
resetCounters,
|
|
77
|
+
} from '@xivdyetools/test-utils/factories';
|
|
78
|
+
|
|
79
|
+
// Create mock domain objects
|
|
80
|
+
const preset = createMockPreset({ name: 'Custom Name' });
|
|
81
|
+
const row = createMockPresetRow({ status: 'pending' });
|
|
82
|
+
const submission = createMockSubmission();
|
|
83
|
+
|
|
84
|
+
// Reset auto-increment counters between tests
|
|
85
|
+
beforeEach(() => resetCounters());
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### DOM Utilities
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { MockLocalStorage, setupCanvasMocks, setupResizeObserverMock } from '@xivdyetools/test-utils/dom';
|
|
92
|
+
|
|
93
|
+
// Mock localStorage
|
|
94
|
+
const storage = new MockLocalStorage();
|
|
95
|
+
global.localStorage = storage;
|
|
96
|
+
|
|
97
|
+
// Setup canvas mocks for chart testing
|
|
98
|
+
setupCanvasMocks();
|
|
99
|
+
|
|
100
|
+
// Setup ResizeObserver mock
|
|
101
|
+
setupResizeObserverMock();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Assertions
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { assertJsonResponse } from '@xivdyetools/test-utils/assertions';
|
|
108
|
+
|
|
109
|
+
const response = await app.request('/api/v1/presets');
|
|
110
|
+
const body = await assertJsonResponse<{ presets: Preset[] }>(response, 200);
|
|
111
|
+
expect(body.presets).toHaveLength(1);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Constants
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { VALID_CODE_VERIFIER, VALID_CODE_CHALLENGE } from '@xivdyetools/test-utils/constants';
|
|
118
|
+
|
|
119
|
+
// RFC 7636 compliant PKCE test values
|
|
120
|
+
const params = new URLSearchParams({
|
|
121
|
+
code_verifier: VALID_CODE_VERIFIER,
|
|
122
|
+
code_challenge: VALID_CODE_CHALLENGE,
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Subpath Exports
|
|
127
|
+
|
|
128
|
+
| Import Path | Contents |
|
|
129
|
+
|-------------|----------|
|
|
130
|
+
| `@xivdyetools/test-utils` | All exports |
|
|
131
|
+
| `@xivdyetools/test-utils/cloudflare` | Cloudflare Workers mocks |
|
|
132
|
+
| `@xivdyetools/test-utils/auth` | Authentication helpers |
|
|
133
|
+
| `@xivdyetools/test-utils/factories` | Domain object factories |
|
|
134
|
+
| `@xivdyetools/test-utils/dom` | DOM/browser utilities |
|
|
135
|
+
| `@xivdyetools/test-utils/assertions` | Response assertions |
|
|
136
|
+
| `@xivdyetools/test-utils/constants` | Test constants (PKCE, etc.) |
|
|
137
|
+
|
|
138
|
+
## TypeScript
|
|
139
|
+
|
|
140
|
+
This package includes full TypeScript support. Cloudflare Workers types are included via `@cloudflare/workers-types`.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response assertion helpers for API testing
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for asserting HTTP response status and body.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const response = await app.request('/api/presets');
|
|
9
|
+
*
|
|
10
|
+
* // Assert status and get typed body
|
|
11
|
+
* const body = await assertJsonResponse<{ presets: Preset[] }>(response, 200);
|
|
12
|
+
* expect(body.presets).toHaveLength(1);
|
|
13
|
+
*
|
|
14
|
+
* // Assert error response
|
|
15
|
+
* const error = await assertErrorResponse(response, 400);
|
|
16
|
+
* expect(error.error).toBe('Validation failed');
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Assert response has expected status and return JSON body
|
|
21
|
+
*
|
|
22
|
+
* @param response - The Response object
|
|
23
|
+
* @param expectedStatus - Expected HTTP status code
|
|
24
|
+
* @returns The parsed JSON body
|
|
25
|
+
* @throws If status doesn't match
|
|
26
|
+
*/
|
|
27
|
+
export declare function assertJsonResponse<T>(response: Response, expectedStatus: number): Promise<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Error response shape
|
|
30
|
+
*/
|
|
31
|
+
export interface ErrorResponse {
|
|
32
|
+
error: string;
|
|
33
|
+
code?: string;
|
|
34
|
+
details?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Assert response is an error with expected status
|
|
38
|
+
*
|
|
39
|
+
* @param response - The Response object
|
|
40
|
+
* @param expectedStatus - Expected HTTP status code
|
|
41
|
+
* @returns The parsed error body
|
|
42
|
+
* @throws If status doesn't match
|
|
43
|
+
*/
|
|
44
|
+
export declare function assertErrorResponse(response: Response, expectedStatus: number): Promise<ErrorResponse>;
|
|
45
|
+
/**
|
|
46
|
+
* Assert response is OK (2xx status)
|
|
47
|
+
*
|
|
48
|
+
* @param response - The Response object
|
|
49
|
+
* @returns The parsed JSON body
|
|
50
|
+
* @throws If status is not 2xx
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertOkResponse<T>(response: Response): Promise<T>;
|
|
53
|
+
/**
|
|
54
|
+
* Assert response is a redirect
|
|
55
|
+
*
|
|
56
|
+
* @param response - The Response object
|
|
57
|
+
* @param expectedLocation - Optional expected Location header value
|
|
58
|
+
* @returns The Location header value
|
|
59
|
+
* @throws If not a redirect or location doesn't match
|
|
60
|
+
*/
|
|
61
|
+
export declare function assertRedirectResponse(response: Response, expectedLocation?: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Assert response has specific headers
|
|
64
|
+
*
|
|
65
|
+
* @param response - The Response object
|
|
66
|
+
* @param expectedHeaders - Headers to check
|
|
67
|
+
* @throws If any header is missing or doesn't match
|
|
68
|
+
*/
|
|
69
|
+
export declare function assertHeaders(response: Response, expectedHeaders: Record<string, string>): void;
|
|
70
|
+
/**
|
|
71
|
+
* Assert response has CORS headers
|
|
72
|
+
*
|
|
73
|
+
* @param response - The Response object
|
|
74
|
+
* @param origin - Expected allowed origin
|
|
75
|
+
*/
|
|
76
|
+
export declare function assertCorsHeaders(response: Response, origin?: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Assert response is JSON content type
|
|
79
|
+
*
|
|
80
|
+
* @param response - The Response object
|
|
81
|
+
* @throws If Content-Type is not application/json
|
|
82
|
+
*/
|
|
83
|
+
export declare function assertJsonContentType(response: Response): void;
|
|
84
|
+
//# sourceMappingURL=response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/assertions/response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,CAAC,CAAC,CASZ;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC,CAExB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CASxE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,CAsBR;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,IAAI,CASN;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAY3E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAQ9D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response assertion helpers for API testing
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for asserting HTTP response status and body.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const response = await app.request('/api/presets');
|
|
9
|
+
*
|
|
10
|
+
* // Assert status and get typed body
|
|
11
|
+
* const body = await assertJsonResponse<{ presets: Preset[] }>(response, 200);
|
|
12
|
+
* expect(body.presets).toHaveLength(1);
|
|
13
|
+
*
|
|
14
|
+
* // Assert error response
|
|
15
|
+
* const error = await assertErrorResponse(response, 400);
|
|
16
|
+
* expect(error.error).toBe('Validation failed');
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
// Note: We use a dynamic import approach to avoid hard dependency on vitest
|
|
20
|
+
// Tests should import { expect } from 'vitest' separately
|
|
21
|
+
/**
|
|
22
|
+
* Assert response has expected status and return JSON body
|
|
23
|
+
*
|
|
24
|
+
* @param response - The Response object
|
|
25
|
+
* @param expectedStatus - Expected HTTP status code
|
|
26
|
+
* @returns The parsed JSON body
|
|
27
|
+
* @throws If status doesn't match
|
|
28
|
+
*/
|
|
29
|
+
export async function assertJsonResponse(response, expectedStatus) {
|
|
30
|
+
if (response.status !== expectedStatus) {
|
|
31
|
+
const body = await response.text();
|
|
32
|
+
throw new Error(`Expected status ${expectedStatus}, got ${response.status}. Body: ${body}`);
|
|
33
|
+
}
|
|
34
|
+
return response.json();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Assert response is an error with expected status
|
|
38
|
+
*
|
|
39
|
+
* @param response - The Response object
|
|
40
|
+
* @param expectedStatus - Expected HTTP status code
|
|
41
|
+
* @returns The parsed error body
|
|
42
|
+
* @throws If status doesn't match
|
|
43
|
+
*/
|
|
44
|
+
export async function assertErrorResponse(response, expectedStatus) {
|
|
45
|
+
return assertJsonResponse(response, expectedStatus);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Assert response is OK (2xx status)
|
|
49
|
+
*
|
|
50
|
+
* @param response - The Response object
|
|
51
|
+
* @returns The parsed JSON body
|
|
52
|
+
* @throws If status is not 2xx
|
|
53
|
+
*/
|
|
54
|
+
export async function assertOkResponse(response) {
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const body = await response.text();
|
|
57
|
+
throw new Error(`Expected OK response, got ${response.status}. Body: ${body}`);
|
|
58
|
+
}
|
|
59
|
+
return response.json();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Assert response is a redirect
|
|
63
|
+
*
|
|
64
|
+
* @param response - The Response object
|
|
65
|
+
* @param expectedLocation - Optional expected Location header value
|
|
66
|
+
* @returns The Location header value
|
|
67
|
+
* @throws If not a redirect or location doesn't match
|
|
68
|
+
*/
|
|
69
|
+
export function assertRedirectResponse(response, expectedLocation) {
|
|
70
|
+
const redirectStatuses = [301, 302, 303, 307, 308];
|
|
71
|
+
if (!redirectStatuses.includes(response.status)) {
|
|
72
|
+
throw new Error(`Expected redirect status (3xx), got ${response.status}`);
|
|
73
|
+
}
|
|
74
|
+
const location = response.headers.get('Location');
|
|
75
|
+
if (!location) {
|
|
76
|
+
throw new Error('Expected Location header in redirect response');
|
|
77
|
+
}
|
|
78
|
+
if (expectedLocation && location !== expectedLocation) {
|
|
79
|
+
throw new Error(`Expected location "${expectedLocation}", got "${location}"`);
|
|
80
|
+
}
|
|
81
|
+
return location;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Assert response has specific headers
|
|
85
|
+
*
|
|
86
|
+
* @param response - The Response object
|
|
87
|
+
* @param expectedHeaders - Headers to check
|
|
88
|
+
* @throws If any header is missing or doesn't match
|
|
89
|
+
*/
|
|
90
|
+
export function assertHeaders(response, expectedHeaders) {
|
|
91
|
+
for (const [key, value] of Object.entries(expectedHeaders)) {
|
|
92
|
+
const actual = response.headers.get(key);
|
|
93
|
+
if (actual !== value) {
|
|
94
|
+
throw new Error(`Expected header "${key}" to be "${value}", got "${actual}"`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Assert response has CORS headers
|
|
100
|
+
*
|
|
101
|
+
* @param response - The Response object
|
|
102
|
+
* @param origin - Expected allowed origin
|
|
103
|
+
*/
|
|
104
|
+
export function assertCorsHeaders(response, origin) {
|
|
105
|
+
const acao = response.headers.get('Access-Control-Allow-Origin');
|
|
106
|
+
if (!acao) {
|
|
107
|
+
throw new Error('Expected Access-Control-Allow-Origin header');
|
|
108
|
+
}
|
|
109
|
+
if (origin && acao !== origin && acao !== '*') {
|
|
110
|
+
throw new Error(`Expected CORS origin "${origin}" or "*", got "${acao}"`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Assert response is JSON content type
|
|
115
|
+
*
|
|
116
|
+
* @param response - The Response object
|
|
117
|
+
* @throws If Content-Type is not application/json
|
|
118
|
+
*/
|
|
119
|
+
export function assertJsonContentType(response) {
|
|
120
|
+
const contentType = response.headers.get('Content-Type');
|
|
121
|
+
if (!contentType?.includes('application/json')) {
|
|
122
|
+
throw new Error(`Expected Content-Type application/json, got "${contentType}"`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/assertions/response.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth context factories for testing middleware and handlers
|
|
3
|
+
*
|
|
4
|
+
* Provides factory functions to create authentication contexts
|
|
5
|
+
* for testing protected endpoints.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Regular authenticated user
|
|
10
|
+
* const userCtx = createAuthContext({ userDiscordId: '123456789' });
|
|
11
|
+
*
|
|
12
|
+
* // Moderator context
|
|
13
|
+
* const modCtx = createModeratorContext();
|
|
14
|
+
*
|
|
15
|
+
* // Unauthenticated context
|
|
16
|
+
* const anonCtx = createUnauthenticatedContext();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import type { AuthContext, AuthSource } from '@xivdyetools/types/auth';
|
|
20
|
+
export type { AuthContext, AuthSource };
|
|
21
|
+
/**
|
|
22
|
+
* Creates an authenticated user context
|
|
23
|
+
*
|
|
24
|
+
* @param overrides - Optional overrides for the default values
|
|
25
|
+
* @returns An AuthContext for an authenticated user
|
|
26
|
+
*/
|
|
27
|
+
export declare function createAuthContext(overrides?: Partial<AuthContext>): AuthContext;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a moderator context
|
|
30
|
+
*
|
|
31
|
+
* @param overrides - Optional overrides for the default values
|
|
32
|
+
* @returns An AuthContext for a moderator
|
|
33
|
+
*/
|
|
34
|
+
export declare function createModeratorContext(overrides?: Partial<AuthContext>): AuthContext;
|
|
35
|
+
/**
|
|
36
|
+
* Creates an unauthenticated context
|
|
37
|
+
*
|
|
38
|
+
* @returns An AuthContext for an unauthenticated request
|
|
39
|
+
*/
|
|
40
|
+
export declare function createUnauthenticatedContext(): AuthContext;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a web-authenticated context (JWT auth)
|
|
43
|
+
*
|
|
44
|
+
* @param overrides - Optional overrides for the default values
|
|
45
|
+
* @returns An AuthContext for a web-authenticated user
|
|
46
|
+
*/
|
|
47
|
+
export declare function createWebAuthContext(overrides?: Partial<AuthContext>): AuthContext;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a bot-authenticated context
|
|
50
|
+
*
|
|
51
|
+
* @param overrides - Optional overrides for the default values
|
|
52
|
+
* @returns An AuthContext for a bot-authenticated user
|
|
53
|
+
*/
|
|
54
|
+
export declare function createBotAuthContext(overrides?: Partial<AuthContext>): AuthContext;
|
|
55
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGvE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CASnF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CASxF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,WAAW,CAM1D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAStF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAStF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth context factories for testing middleware and handlers
|
|
3
|
+
*
|
|
4
|
+
* Provides factory functions to create authentication contexts
|
|
5
|
+
* for testing protected endpoints.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Regular authenticated user
|
|
10
|
+
* const userCtx = createAuthContext({ userDiscordId: '123456789' });
|
|
11
|
+
*
|
|
12
|
+
* // Moderator context
|
|
13
|
+
* const modCtx = createModeratorContext();
|
|
14
|
+
*
|
|
15
|
+
* // Unauthenticated context
|
|
16
|
+
* const anonCtx = createUnauthenticatedContext();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Creates an authenticated user context
|
|
21
|
+
*
|
|
22
|
+
* @param overrides - Optional overrides for the default values
|
|
23
|
+
* @returns An AuthContext for an authenticated user
|
|
24
|
+
*/
|
|
25
|
+
export function createAuthContext(overrides = {}) {
|
|
26
|
+
return {
|
|
27
|
+
isAuthenticated: true,
|
|
28
|
+
isModerator: false,
|
|
29
|
+
userDiscordId: '123456789',
|
|
30
|
+
userName: 'TestUser',
|
|
31
|
+
authSource: 'bot',
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a moderator context
|
|
37
|
+
*
|
|
38
|
+
* @param overrides - Optional overrides for the default values
|
|
39
|
+
* @returns An AuthContext for a moderator
|
|
40
|
+
*/
|
|
41
|
+
export function createModeratorContext(overrides = {}) {
|
|
42
|
+
return {
|
|
43
|
+
isAuthenticated: true,
|
|
44
|
+
isModerator: true,
|
|
45
|
+
userDiscordId: '123456789',
|
|
46
|
+
userName: 'ModeratorUser',
|
|
47
|
+
authSource: 'bot',
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates an unauthenticated context
|
|
53
|
+
*
|
|
54
|
+
* @returns An AuthContext for an unauthenticated request
|
|
55
|
+
*/
|
|
56
|
+
export function createUnauthenticatedContext() {
|
|
57
|
+
return {
|
|
58
|
+
isAuthenticated: false,
|
|
59
|
+
isModerator: false,
|
|
60
|
+
authSource: 'none',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Creates a web-authenticated context (JWT auth)
|
|
65
|
+
*
|
|
66
|
+
* @param overrides - Optional overrides for the default values
|
|
67
|
+
* @returns An AuthContext for a web-authenticated user
|
|
68
|
+
*/
|
|
69
|
+
export function createWebAuthContext(overrides = {}) {
|
|
70
|
+
return {
|
|
71
|
+
isAuthenticated: true,
|
|
72
|
+
isModerator: false,
|
|
73
|
+
userDiscordId: '123456789',
|
|
74
|
+
userName: 'WebUser',
|
|
75
|
+
authSource: 'web',
|
|
76
|
+
...overrides,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Creates a bot-authenticated context
|
|
81
|
+
*
|
|
82
|
+
* @param overrides - Optional overrides for the default values
|
|
83
|
+
* @returns An AuthContext for a bot-authenticated user
|
|
84
|
+
*/
|
|
85
|
+
export function createBotAuthContext(overrides = {}) {
|
|
86
|
+
return {
|
|
87
|
+
isAuthenticated: true,
|
|
88
|
+
isModerator: false,
|
|
89
|
+
userDiscordId: '123456789',
|
|
90
|
+
userName: 'BotUser',
|
|
91
|
+
authSource: 'bot',
|
|
92
|
+
...overrides,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAkC,EAAE;IACpE,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,UAAU;QACpB,UAAU,EAAE,KAAK;QACjB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAAkC,EAAE;IACzE,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;QACjB,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,eAAe;QACzB,UAAU,EAAE,KAAK;QACjB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B;IAC1C,OAAO;QACL,eAAe,EAAE,KAAK;QACtB,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,MAAM;KACnB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAkC,EAAE;IACvE,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,KAAK;QACjB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAkC,EAAE;IACvE,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,WAAW;QAC1B,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,KAAK;QACjB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request header builders for testing API authentication
|
|
3
|
+
*
|
|
4
|
+
* Provides helper functions to build authentication headers
|
|
5
|
+
* for testing API endpoints.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // JWT auth headers
|
|
10
|
+
* const headers = authHeaders(jwt);
|
|
11
|
+
*
|
|
12
|
+
* // Bot auth headers with signature
|
|
13
|
+
* const botHeaders = await authHeadersWithSignature(
|
|
14
|
+
* 'bot-token',
|
|
15
|
+
* 'user-id',
|
|
16
|
+
* 'username'
|
|
17
|
+
* );
|
|
18
|
+
*
|
|
19
|
+
* // Use in requests
|
|
20
|
+
* const response = await fetch('/api/protected', { headers });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Creates basic auth headers with a bearer token
|
|
25
|
+
*
|
|
26
|
+
* @param token - The bearer token (JWT or API key)
|
|
27
|
+
* @param userId - Optional Discord user ID
|
|
28
|
+
* @param userName - Optional Discord username
|
|
29
|
+
* @returns Headers object
|
|
30
|
+
*/
|
|
31
|
+
export declare function authHeaders(token: string, userId?: string, userName?: string): Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Creates auth headers with HMAC signature for bot authentication
|
|
34
|
+
*
|
|
35
|
+
* @param token - The bot API token
|
|
36
|
+
* @param userId - Discord user ID (optional)
|
|
37
|
+
* @param userName - Discord username (optional)
|
|
38
|
+
* @param signingSecret - The signing secret (defaults to TEST_SIGNING_SECRET)
|
|
39
|
+
* @returns Headers object with signature
|
|
40
|
+
*/
|
|
41
|
+
export declare function authHeadersWithSignature(token: string, userId?: string, userName?: string, signingSecret?: string): Promise<Record<string, string>>;
|
|
42
|
+
/**
|
|
43
|
+
* Creates JSON content headers
|
|
44
|
+
*
|
|
45
|
+
* @returns Headers object with Content-Type: application/json
|
|
46
|
+
*/
|
|
47
|
+
export declare function jsonHeaders(): Record<string, string>;
|
|
48
|
+
/**
|
|
49
|
+
* Merges multiple header objects
|
|
50
|
+
*
|
|
51
|
+
* @param headerObjects - Header objects to merge
|
|
52
|
+
* @returns Merged headers object
|
|
53
|
+
*/
|
|
54
|
+
export declare function mergeHeaders(...headerObjects: Record<string, string>[]): Record<string, string>;
|
|
55
|
+
/**
|
|
56
|
+
* Creates authenticated JSON request headers
|
|
57
|
+
*
|
|
58
|
+
* @param token - The bearer token
|
|
59
|
+
* @param userId - Optional Discord user ID
|
|
60
|
+
* @param userName - Optional Discord username
|
|
61
|
+
* @returns Headers object with auth and content-type
|
|
62
|
+
*/
|
|
63
|
+
export declare function authenticatedJsonHeaders(token: string, userId?: string, userName?: string): Record<string, string>;
|
|
64
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/auth/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,GAAE,MAA4B,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA2BjC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIpD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB"}
|