@redseat/api 0.0.11 → 0.0.12

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/test.md CHANGED
@@ -1,291 +1,291 @@
1
- # Testing Guide
2
-
3
- This document describes how to run tests for the `@redseat/api` package and what each test file covers.
4
-
5
- ## Running Tests
6
-
7
- ### Run All Tests
8
-
9
- ```bash
10
- npm test
11
- ```
12
-
13
- This runs all tests once and exits.
14
-
15
- ### Run Tests in Watch Mode
16
-
17
- ```bash
18
- npm run test:watch
19
- ```
20
-
21
- This runs tests in watch mode, automatically re-running tests when files change.
22
-
23
- ### Run Specific Test File
24
-
25
- ```bash
26
- npx vitest run src/encryption.test.ts
27
- ```
28
-
29
- ### Run Tests with Coverage
30
-
31
- ```bash
32
- npx vitest run --coverage
33
- ```
34
-
35
- ## Test Framework
36
-
37
- The package uses [Vitest](https://vitest.dev/) as the test framework. Vitest is a fast unit test framework powered by Vite, designed to be compatible with Jest.
38
-
39
- ### Configuration
40
-
41
- Test configuration is in `vitest.config.ts`:
42
- - Environment: Node.js
43
- - Globals: Enabled (no need to import `describe`, `it`, `expect`)
44
-
45
- ## Test Files
46
-
47
- ### `src/encryption.test.ts`
48
-
49
- Tests for the encryption module (`src/encryption.ts`).
50
-
51
- **What it tests:**
52
- - **Key Derivation (`deriveKey`)**
53
- - Derives text keys from passphrases
54
- - Derives file keys from passphrases
55
- - Verifies text and file keys are different (different salts)
56
- - Verifies same passphrase produces same key
57
-
58
- - **IV Generation (`getRandomIV`)**
59
- - Generates 16-byte IVs
60
- - Generates different IVs on each call
61
-
62
- - **Text Encryption/Decryption (`encryptText` / `decryptText`)**
63
- - Encrypts and decrypts text correctly
64
- - Produces different encrypted output for same text (due to random IV)
65
- - Handles empty strings
66
- - Handles special characters and unicode
67
- - Verifies encrypted format: `${IV}.${encryptedData}` (base64url)
68
-
69
- - **Buffer Encryption/Decryption (`encryptBuffer` / `decryptBuffer`)**
70
- - Encrypts and decrypts binary data correctly
71
- - Requires correct IV for decryption
72
- - Handles empty buffers
73
- - Handles large buffers
74
-
75
- - **File Encryption (`encryptFile`)**
76
- - Encrypts files with thumbnails
77
- - Encrypts files without thumbnails
78
- - Includes correct MIME types in encrypted structure
79
- - Returns correct IV and thumbnail size
80
-
81
- - **File Decryption (`decryptFile` / `decryptFileThumb`)**
82
- - Decrypts file data from encrypted structure
83
- - Decrypts thumbnail data from encrypted structure
84
- - Handles files without thumbnails
85
- - Verifies file format structure (IV, sizes, MIME types, data)
86
-
87
- - **Filename Encryption (`encryptFilename`)**
88
- - Encrypts filenames with given IV
89
- - Returns base64url encoded encrypted filename
90
-
91
- - **Endianness Compatibility**
92
- - Handles both big-endian and little-endian size fields
93
- - Backward compatibility with old file formats
94
-
95
- **Example test:**
96
- ```typescript
97
- it('should encrypt and decrypt text correctly', async () => {
98
- const key = await deriveKey('password', 'text');
99
- const encrypted = await encryptText(key, 'Hello World');
100
- const decrypted = await decryptText(key, encrypted);
101
- expect(decrypted).toBe('Hello World');
102
- });
103
- ```
104
-
105
- ---
106
-
107
- ### `src/crypto.test.ts`
108
-
109
- Tests for crypto utility functions (`src/crypto.ts`).
110
-
111
- **What it tests:**
112
- - **Platform Detection (`getCryptoSubtle` / `getCryptoRandomValues`)**
113
- - Returns SubtleCrypto instance
114
- - Returns random number generator function
115
- - Works in Node.js environment
116
-
117
- - **Base64 Encoding/Decoding**
118
- - `uint8ArrayFromBase64`: Converts base64 to Uint8Array
119
- - `uint8ArrayFromBase64Url`: Converts base64url to Uint8Array
120
- - `arrayBufferToBase64`: Converts ArrayBuffer to base64
121
- - Handles padding correctly
122
- - Handles base64url format (dashes and underscores)
123
-
124
- - **Base64 URL Conversion**
125
- - `base64ToBase64Url`: Converts standard base64 to base64url
126
- - `base64UrlToBase64`: Converts base64url to standard base64
127
- - Handles character substitution (`+`/`-`, `/`/`_`)
128
- - Handles padding removal/addition
129
-
130
- - **String Padding (`padRight`)**
131
- - Pads strings to specified length
132
- - Handles strings longer than target length
133
- - Handles empty strings
134
- - Uses correct padding character
135
-
136
- **Example test:**
137
- ```typescript
138
- it('should convert base64 string to Uint8Array', () => {
139
- const base64 = 'SGVsbG8gV29ybGQ='; // "Hello World"
140
- const result = uint8ArrayFromBase64(base64);
141
- expect(result).toBeInstanceOf(Uint8Array);
142
- expect(String.fromCharCode(...result)).toBe('Hello World');
143
- });
144
- ```
145
-
146
- ---
147
-
148
- ### `src/library-upload.test.ts`
149
-
150
- Tests for `LibraryApi.uploadMedia()` method.
151
-
152
- **What it tests:**
153
- - **Encrypted Library Uploads**
154
- - Throws error if encryption key is not set
155
- - Encrypts data when key is set via `setKey()`
156
- - Encrypts filename using text encryption
157
- - Includes IV and thumbnail size in metadata
158
- - Handles thumbnail encryption
159
- - Validates thumbnail can only be specified for encrypted libraries
160
-
161
- - **Non-Encrypted Library Uploads**
162
- - Uploads without encryption
163
- - Uses original filename
164
- - Does not require encryption key
165
-
166
- - **Input Validation**
167
- - Handles ArrayBuffer input
168
- - Handles Uint8Array input
169
- - Normalizes different buffer types correctly
170
- - Validates metadata structure
171
-
172
- - **FormData Structure**
173
- - Creates FormData with correct structure
174
- - Info field is first, file field is last
175
- - Includes correct metadata in info field
176
- - Uses correct filename in file field
177
-
178
- - **Progress Callback**
179
- - Calls progress callback during upload
180
- - Provides correct loaded/total values
181
-
182
- - **Error Handling**
183
- - Throws appropriate errors for missing keys
184
- - Throws errors for invalid configurations
185
- - Handles network errors gracefully
186
-
187
- **Example test:**
188
- ```typescript
189
- it('should throw error if key is not set', async () => {
190
- libraryApi = new LibraryApi(client, 'lib1', encryptedLibrary);
191
- await expect(
192
- libraryApi.uploadMedia(data, {
193
- metadata: {},
194
- fileMime: 'image/jpeg'
195
- })
196
- ).rejects.toThrow('Encryption key not set');
197
- });
198
- ```
199
-
200
- ---
201
-
202
- ## Test Structure
203
-
204
- All test files follow this structure:
205
-
206
- ```typescript
207
- import { describe, it, expect } from 'vitest';
208
- import { /* functions to test */ } from './module';
209
-
210
- describe('Module Name', () => {
211
- describe('Function Group', () => {
212
- it('should do something', () => {
213
- // Test implementation
214
- });
215
- });
216
- });
217
- ```
218
-
219
- ## Writing New Tests
220
-
221
- When adding new functionality:
222
-
223
- 1. **Add tests to existing file** if testing existing module
224
- 2. **Create new test file** if testing new module (follow naming: `module-name.test.ts`)
225
- 3. **Test both success and error cases**
226
- 4. **Test edge cases** (empty inputs, null values, etc.)
227
- 5. **Use descriptive test names** that explain what is being tested
228
-
229
- ### Example: Adding Test for New Function
230
-
231
- ```typescript
232
- // In appropriate test file
233
- describe('newFunction', () => {
234
- it('should handle normal case', () => {
235
- const result = newFunction('input');
236
- expect(result).toBe('expected');
237
- });
238
-
239
- it('should handle edge case', () => {
240
- const result = newFunction('');
241
- expect(result).toBe('');
242
- });
243
-
244
- it('should throw error for invalid input', () => {
245
- expect(() => newFunction(null)).toThrow();
246
- });
247
- });
248
- ```
249
-
250
- ## Continuous Integration
251
-
252
- Tests should be run:
253
- - Before committing code
254
- - In CI/CD pipeline
255
- - Before releasing new versions
256
-
257
- ## Coverage Goals
258
-
259
- Aim for:
260
- - **High coverage** on core functionality (encryption, API methods)
261
- - **Edge case coverage** for error handling
262
- - **Integration tests** for complex workflows
263
-
264
- ## Debugging Tests
265
-
266
- ### Run Single Test
267
-
268
- ```bash
269
- npx vitest run -t "test name"
270
- ```
271
-
272
- ### Debug Mode
273
-
274
- ```bash
275
- node --inspect-brk node_modules/.bin/vitest run
276
- ```
277
-
278
- Then attach debugger in VS Code or Chrome DevTools.
279
-
280
- ### Verbose Output
281
-
282
- ```bash
283
- npx vitest run --reporter=verbose
284
- ```
285
-
286
- ## Related Documentation
287
-
288
- - [Vitest Documentation](https://vitest.dev/)
289
- - [Encryption Documentation](encryption.md) - Details on encryption functions being tested
290
- - [README](README.md) - Package overview
291
-
1
+ # Testing Guide
2
+
3
+ This document describes how to run tests for the `@redseat/api` package and what each test file covers.
4
+
5
+ ## Running Tests
6
+
7
+ ### Run All Tests
8
+
9
+ ```bash
10
+ npm test
11
+ ```
12
+
13
+ This runs all tests once and exits.
14
+
15
+ ### Run Tests in Watch Mode
16
+
17
+ ```bash
18
+ npm run test:watch
19
+ ```
20
+
21
+ This runs tests in watch mode, automatically re-running tests when files change.
22
+
23
+ ### Run Specific Test File
24
+
25
+ ```bash
26
+ npx vitest run src/encryption.test.ts
27
+ ```
28
+
29
+ ### Run Tests with Coverage
30
+
31
+ ```bash
32
+ npx vitest run --coverage
33
+ ```
34
+
35
+ ## Test Framework
36
+
37
+ The package uses [Vitest](https://vitest.dev/) as the test framework. Vitest is a fast unit test framework powered by Vite, designed to be compatible with Jest.
38
+
39
+ ### Configuration
40
+
41
+ Test configuration is in `vitest.config.ts`:
42
+ - Environment: Node.js
43
+ - Globals: Enabled (no need to import `describe`, `it`, `expect`)
44
+
45
+ ## Test Files
46
+
47
+ ### `src/encryption.test.ts`
48
+
49
+ Tests for the encryption module (`src/encryption.ts`).
50
+
51
+ **What it tests:**
52
+ - **Key Derivation (`deriveKey`)**
53
+ - Derives text keys from passphrases
54
+ - Derives file keys from passphrases
55
+ - Verifies text and file keys are different (different salts)
56
+ - Verifies same passphrase produces same key
57
+
58
+ - **IV Generation (`getRandomIV`)**
59
+ - Generates 16-byte IVs
60
+ - Generates different IVs on each call
61
+
62
+ - **Text Encryption/Decryption (`encryptText` / `decryptText`)**
63
+ - Encrypts and decrypts text correctly
64
+ - Produces different encrypted output for same text (due to random IV)
65
+ - Handles empty strings
66
+ - Handles special characters and unicode
67
+ - Verifies encrypted format: `${IV}.${encryptedData}` (base64url)
68
+
69
+ - **Buffer Encryption/Decryption (`encryptBuffer` / `decryptBuffer`)**
70
+ - Encrypts and decrypts binary data correctly
71
+ - Requires correct IV for decryption
72
+ - Handles empty buffers
73
+ - Handles large buffers
74
+
75
+ - **File Encryption (`encryptFile`)**
76
+ - Encrypts files with thumbnails
77
+ - Encrypts files without thumbnails
78
+ - Includes correct MIME types in encrypted structure
79
+ - Returns correct IV and thumbnail size
80
+
81
+ - **File Decryption (`decryptFile` / `decryptFileThumb`)**
82
+ - Decrypts file data from encrypted structure
83
+ - Decrypts thumbnail data from encrypted structure
84
+ - Handles files without thumbnails
85
+ - Verifies file format structure (IV, sizes, MIME types, data)
86
+
87
+ - **Filename Encryption (`encryptFilename`)**
88
+ - Encrypts filenames with given IV
89
+ - Returns base64url encoded encrypted filename
90
+
91
+ - **Endianness Compatibility**
92
+ - Handles both big-endian and little-endian size fields
93
+ - Backward compatibility with old file formats
94
+
95
+ **Example test:**
96
+ ```typescript
97
+ it('should encrypt and decrypt text correctly', async () => {
98
+ const key = await deriveKey('password', 'text');
99
+ const encrypted = await encryptText(key, 'Hello World');
100
+ const decrypted = await decryptText(key, encrypted);
101
+ expect(decrypted).toBe('Hello World');
102
+ });
103
+ ```
104
+
105
+ ---
106
+
107
+ ### `src/crypto.test.ts`
108
+
109
+ Tests for crypto utility functions (`src/crypto.ts`).
110
+
111
+ **What it tests:**
112
+ - **Platform Detection (`getCryptoSubtle` / `getCryptoRandomValues`)**
113
+ - Returns SubtleCrypto instance
114
+ - Returns random number generator function
115
+ - Works in Node.js environment
116
+
117
+ - **Base64 Encoding/Decoding**
118
+ - `uint8ArrayFromBase64`: Converts base64 to Uint8Array
119
+ - `uint8ArrayFromBase64Url`: Converts base64url to Uint8Array
120
+ - `arrayBufferToBase64`: Converts ArrayBuffer to base64
121
+ - Handles padding correctly
122
+ - Handles base64url format (dashes and underscores)
123
+
124
+ - **Base64 URL Conversion**
125
+ - `base64ToBase64Url`: Converts standard base64 to base64url
126
+ - `base64UrlToBase64`: Converts base64url to standard base64
127
+ - Handles character substitution (`+`/`-`, `/`/`_`)
128
+ - Handles padding removal/addition
129
+
130
+ - **String Padding (`padRight`)**
131
+ - Pads strings to specified length
132
+ - Handles strings longer than target length
133
+ - Handles empty strings
134
+ - Uses correct padding character
135
+
136
+ **Example test:**
137
+ ```typescript
138
+ it('should convert base64 string to Uint8Array', () => {
139
+ const base64 = 'SGVsbG8gV29ybGQ='; // "Hello World"
140
+ const result = uint8ArrayFromBase64(base64);
141
+ expect(result).toBeInstanceOf(Uint8Array);
142
+ expect(String.fromCharCode(...result)).toBe('Hello World');
143
+ });
144
+ ```
145
+
146
+ ---
147
+
148
+ ### `src/library-upload.test.ts`
149
+
150
+ Tests for `LibraryApi.uploadMedia()` method.
151
+
152
+ **What it tests:**
153
+ - **Encrypted Library Uploads**
154
+ - Throws error if encryption key is not set
155
+ - Encrypts data when key is set via `setKey()`
156
+ - Encrypts filename using text encryption
157
+ - Includes IV and thumbnail size in metadata
158
+ - Handles thumbnail encryption
159
+ - Validates thumbnail can only be specified for encrypted libraries
160
+
161
+ - **Non-Encrypted Library Uploads**
162
+ - Uploads without encryption
163
+ - Uses original filename
164
+ - Does not require encryption key
165
+
166
+ - **Input Validation**
167
+ - Handles ArrayBuffer input
168
+ - Handles Uint8Array input
169
+ - Normalizes different buffer types correctly
170
+ - Validates metadata structure
171
+
172
+ - **FormData Structure**
173
+ - Creates FormData with correct structure
174
+ - Info field is first, file field is last
175
+ - Includes correct metadata in info field
176
+ - Uses correct filename in file field
177
+
178
+ - **Progress Callback**
179
+ - Calls progress callback during upload
180
+ - Provides correct loaded/total values
181
+
182
+ - **Error Handling**
183
+ - Throws appropriate errors for missing keys
184
+ - Throws errors for invalid configurations
185
+ - Handles network errors gracefully
186
+
187
+ **Example test:**
188
+ ```typescript
189
+ it('should throw error if key is not set', async () => {
190
+ libraryApi = new LibraryApi(client, 'lib1', encryptedLibrary);
191
+ await expect(
192
+ libraryApi.uploadMedia(data, {
193
+ metadata: {},
194
+ fileMime: 'image/jpeg'
195
+ })
196
+ ).rejects.toThrow('Encryption key not set');
197
+ });
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Test Structure
203
+
204
+ All test files follow this structure:
205
+
206
+ ```typescript
207
+ import { describe, it, expect } from 'vitest';
208
+ import { /* functions to test */ } from './module';
209
+
210
+ describe('Module Name', () => {
211
+ describe('Function Group', () => {
212
+ it('should do something', () => {
213
+ // Test implementation
214
+ });
215
+ });
216
+ });
217
+ ```
218
+
219
+ ## Writing New Tests
220
+
221
+ When adding new functionality:
222
+
223
+ 1. **Add tests to existing file** if testing existing module
224
+ 2. **Create new test file** if testing new module (follow naming: `module-name.test.ts`)
225
+ 3. **Test both success and error cases**
226
+ 4. **Test edge cases** (empty inputs, null values, etc.)
227
+ 5. **Use descriptive test names** that explain what is being tested
228
+
229
+ ### Example: Adding Test for New Function
230
+
231
+ ```typescript
232
+ // In appropriate test file
233
+ describe('newFunction', () => {
234
+ it('should handle normal case', () => {
235
+ const result = newFunction('input');
236
+ expect(result).toBe('expected');
237
+ });
238
+
239
+ it('should handle edge case', () => {
240
+ const result = newFunction('');
241
+ expect(result).toBe('');
242
+ });
243
+
244
+ it('should throw error for invalid input', () => {
245
+ expect(() => newFunction(null)).toThrow();
246
+ });
247
+ });
248
+ ```
249
+
250
+ ## Continuous Integration
251
+
252
+ Tests should be run:
253
+ - Before committing code
254
+ - In CI/CD pipeline
255
+ - Before releasing new versions
256
+
257
+ ## Coverage Goals
258
+
259
+ Aim for:
260
+ - **High coverage** on core functionality (encryption, API methods)
261
+ - **Edge case coverage** for error handling
262
+ - **Integration tests** for complex workflows
263
+
264
+ ## Debugging Tests
265
+
266
+ ### Run Single Test
267
+
268
+ ```bash
269
+ npx vitest run -t "test name"
270
+ ```
271
+
272
+ ### Debug Mode
273
+
274
+ ```bash
275
+ node --inspect-brk node_modules/.bin/vitest run
276
+ ```
277
+
278
+ Then attach debugger in VS Code or Chrome DevTools.
279
+
280
+ ### Verbose Output
281
+
282
+ ```bash
283
+ npx vitest run --reporter=verbose
284
+ ```
285
+
286
+ ## Related Documentation
287
+
288
+ - [Vitest Documentation](https://vitest.dev/)
289
+ - [Encryption Documentation](encryption.md) - Details on encryption functions being tested
290
+ - [README](README.md) - Package overview
291
+