@dichovsky/testrail-api-client 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Igor Magdich
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.
package/README.md ADDED
@@ -0,0 +1,537 @@
1
+ # TestRail API Client
2
+
3
+ [![CI](https://github.com/dichovsky/testrail-api-client/workflows/CI/badge.svg)](https://github.com/dichovsky/testrail-api-client/actions)
4
+ [![npm version](https://badge.fury.io/js/@dichovsky%2Ftestrail-api-client.svg)](https://badge.fury.io/js/@dichovsky%2Ftestrail-api-client)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-6.0+-blue.svg)](https://www.typescriptlang.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ A comprehensive, type-safe TypeScript/JavaScript client for the [TestRail API](https://support.testrail.com/hc/en-us/articles/7077083596436-Introduction-to-the-TestRail-API) with advanced features including intelligent caching, rate limiting, retry logic with exponential backoff, and robust error handling.
9
+
10
+ **Covers the complete TestRail REST API** — all 101 methods across every resource: projects, suites, sections, cases, plans, runs, tests, results, milestones, users, attachments, configurations, datasets, groups, shared steps, variables, reports, and more.
11
+
12
+ ## Features
13
+
14
+ 🚀 **Performance & Reliability**
15
+
16
+ - Intelligent caching system for GET requests to reduce API calls and improve response times
17
+ - Configurable request timeouts (up to 5 minutes) with automatic cleanup
18
+ - Advanced retry logic with exponential backoff (configurable 0-10 retries)
19
+ - Built-in rate limiting to respect TestRail API constraints (configurable)
20
+ - Memory-efficient caching with configurable size limits
21
+ - Automatic cache cleanup with configurable intervals
22
+ - Graceful cleanup on process termination
23
+ - Cross-platform support (Node.js and browser environments)
24
+
25
+ 🛡️ **Security & Validation**
26
+
27
+ - Comprehensive input validation for all configuration and method parameters
28
+ - URL sanitization and email format validation using regex patterns
29
+ - Secure credential handling with Base64 encoding
30
+ - Protection against common injection attacks
31
+ - Runtime validation ensuring all IDs are positive integers
32
+ - Security warnings for insecure HTTP protocol usage
33
+ - Custom error classes with detailed error information
34
+
35
+ 🔧 **Developer Experience**
36
+
37
+ - Full TypeScript support with strict type checking and comprehensive interfaces
38
+ - Custom error classes (TestRailApiError, TestRailValidationError) for better error handling
39
+ - Extensive JSDoc documentation with parameter descriptions
40
+ - Modern ES2022+ features with async/await API throughout
41
+ - Automatic process cleanup handlers for graceful shutdowns
42
+
43
+ ✅ **Quality & Testing**
44
+
45
+ - 97.6%+ test coverage with comprehensive test suite (456+ tests)
46
+ - High branch coverage (98.7%) ensuring thorough edge case testing
47
+ - Strict ESLint configuration with security-focused and TypeScript-specific rules
48
+ - Automated CI/CD with GitHub Actions and matrix testing
49
+ - Cross-platform Node.js compatibility (20.x+)
50
+ - Comprehensive coverage of error scenarios and edge cases
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ npm install @dichovsky/testrail-api-client
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ```typescript
61
+ import { TestRailClient } from '@dichovsky/testrail-api-client';
62
+
63
+ const client = new TestRailClient({
64
+ baseUrl: 'https://your-domain.testrail.io',
65
+ email: 'your-email@example.com',
66
+ apiKey: 'your-api-key',
67
+ });
68
+
69
+ // Get a project
70
+ const project = await client.getProject(1);
71
+ console.log(project.name);
72
+
73
+ // Get all test cases in a suite
74
+ const cases = await client.getCases(projectId, suiteId);
75
+ console.log(`Found ${cases.length} test cases`);
76
+
77
+ // Add a new test result
78
+ const result = await client.addResult(testId, {
79
+ status_id: 1, // Passed
80
+ comment: 'Test passed successfully',
81
+ elapsed: '5m',
82
+ });
83
+ ```
84
+
85
+ ## Configuration
86
+
87
+ The client supports extensive configuration options:
88
+
89
+ ```typescript
90
+ const client = new TestRailClient({
91
+ baseUrl: 'https://your-domain.testrail.io',
92
+ email: 'your-email@example.com',
93
+ apiKey: 'your-api-key',
94
+
95
+ // Performance settings
96
+ timeout: 30000, // Request timeout (30 seconds, max 5 minutes)
97
+ maxRetries: 3, // Maximum retry attempts (0-10)
98
+ enableCache: true, // Enable response caching for GET requests
99
+ cacheTtl: 300000, // Cache TTL (5 minutes)
100
+ cacheCleanupInterval: 60000, // Cache cleanup interval (1 minute)
101
+ maxCacheSize: 1000, // Maximum cache entries (default: 1000)
102
+
103
+ // Rate limiting
104
+ rateLimiter: {
105
+ maxRequests: 100, // Max requests per window
106
+ windowMs: 60000, // Time window (1 minute)
107
+ },
108
+ });
109
+ ```
110
+
111
+ ### Configuration Options
112
+
113
+ | Option | Type | Default | Description |
114
+ | ---------------------- | ------------------- | ------------ | ------------------------------------------------- |
115
+ | `baseUrl` | `string` | **required** | TestRail instance URL (http/https) |
116
+ | `email` | `string` | **required** | TestRail user email (validated format) |
117
+ | `apiKey` | `string` | **required** | TestRail API key |
118
+ | `timeout` | `number` | `30000` | Request timeout in milliseconds (max 5 minutes) |
119
+ | `maxRetries` | `number` | `3` | Maximum retry attempts for failed requests (0-10) |
120
+ | `enableCache` | `boolean` | `true` | Enable caching for GET requests |
121
+ | `cacheTtl` | `number` | `300000` | Cache time-to-live in milliseconds |
122
+ | `cacheCleanupInterval` | `number` | `60000` | Cache cleanup interval (0 to disable) |
123
+ | `maxCacheSize` | `number` | `1000` | Maximum number of entries in cache |
124
+ | `rateLimiter` | `RateLimiterConfig` | See below | Rate limiting configuration |
125
+
126
+ #### Rate Limiter Configuration
127
+
128
+ ```typescript
129
+ rateLimiter: {
130
+ maxRequests: 100, // Maximum requests per time window
131
+ windowMs: 60000, // Time window in milliseconds
132
+ }
133
+ ```
134
+
135
+ ## Error Handling
136
+
137
+ The client provides comprehensive error handling with custom error classes:
138
+
139
+ ```typescript
140
+ import { TestRailApiError, TestRailValidationError } from '@dichovsky/testrail-api-client';
141
+
142
+ try {
143
+ const project = await client.getProject(999);
144
+ } catch (error) {
145
+ if (error instanceof TestRailApiError) {
146
+ console.error('API Error:', error.message);
147
+ console.error('Status:', error.status);
148
+ console.error('Response:', error.response);
149
+ } else if (error instanceof TestRailValidationError) {
150
+ console.error('Validation Error:', error.message);
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Error Types
156
+
157
+ - **`TestRailApiError`**: Thrown for API-related errors (network, HTTP status, etc.)
158
+ - **`TestRailValidationError`**: Thrown for invalid configuration or parameter validation (e.g., invalid IDs)
159
+ - **Retry Logic**: Automatic retries for 500+ status codes and network errors with exponential backoff
160
+ - **Timeout Handling**: Requests timeout based on configuration (default: 30s)
161
+
162
+ ## Advanced Features
163
+
164
+ ### Caching System
165
+
166
+ - Automatic caching of GET requests to improve performance
167
+ - Configurable TTL and cleanup intervals
168
+ - Memory-efficient with automatic expiration
169
+ - Thread-safe implementation
170
+
171
+ ### Rate Limiting
172
+
173
+ - Built-in rate limiting to respect API constraints
174
+ - Sliding window implementation
175
+ - Configurable limits per time window
176
+ - Exceeds configured limits by throwing a `TestRailApiError` rather than queueing requests
177
+
178
+ ### Retry Logic
179
+
180
+ - Exponential backoff for failed requests
181
+ - Configurable retry attempts (0-10)
182
+ - Smart retry for appropriate error types (500+, network errors)
183
+ - Maximum delay capping to prevent excessive waiting
184
+
185
+ ### Resource Management
186
+
187
+ - Automatic cleanup on process termination
188
+ - Proper timer management for cache cleanup
189
+ - Memory leak prevention with `destroy()` method
190
+ - Graceful shutdown handling
191
+
192
+ ```typescript
193
+ // Explicitly cleanup resources when done
194
+ client.destroy();
195
+ ```
196
+
197
+ ## API Methods
198
+
199
+ ### Projects
200
+
201
+ ```typescript
202
+ // Get project by ID
203
+ const project = await client.getProject(projectId);
204
+
205
+ // Get all projects
206
+ const projects = await client.getProjects();
207
+ ```
208
+
209
+ ### Suites
210
+
211
+ ```typescript
212
+ // Get suite by ID
213
+ const suite = await client.getSuite(suiteId);
214
+
215
+ // Get all suites for a project
216
+ const suites = await client.getSuites(projectId);
217
+ ```
218
+
219
+ ### Sections
220
+
221
+ ```typescript
222
+ // Get section by ID
223
+ const section = await client.getSection(sectionId);
224
+
225
+ // Get all sections (optionally filtered by suite)
226
+ const sections = await client.getSections(projectId, suiteId);
227
+ ```
228
+
229
+ ### Test Cases
230
+
231
+ ```typescript
232
+ // Get case by ID
233
+ const testCase = await client.getCase(caseId);
234
+
235
+ // Get all cases (optionally filtered by suite/section)
236
+ const cases = await client.getCases(projectId, suiteId, sectionId);
237
+
238
+ // Add a new test case
239
+ const newCase = await client.addCase(sectionId, {
240
+ title: 'New test case',
241
+ type_id: 1,
242
+ priority_id: 2,
243
+ estimate: '5m',
244
+ });
245
+
246
+ // Update a test case
247
+ const updatedCase = await client.updateCase(caseId, {
248
+ title: 'Updated test case title',
249
+ });
250
+
251
+ // Delete a test case
252
+ await client.deleteCase(caseId);
253
+ ```
254
+
255
+ ### Test Plans
256
+
257
+ ```typescript
258
+ // Get plan by ID
259
+ const plan = await client.getPlan(planId);
260
+
261
+ // Get all plans for a project
262
+ const plans = await client.getPlans(projectId);
263
+
264
+ // Add a new plan
265
+ const newPlan = await client.addPlan(projectId, {
266
+ name: 'Automated Test Plan',
267
+ entries: [
268
+ {
269
+ suite_id: suiteId,
270
+ include_all: true,
271
+ },
272
+ ],
273
+ });
274
+
275
+ // Close a plan
276
+ await client.closePlan(planId);
277
+
278
+ // Delete a plan
279
+ await client.deletePlan(planId);
280
+ ```
281
+
282
+ ### Test Runs
283
+
284
+ ```typescript
285
+ // Get run by ID
286
+ const run = await client.getRun(runId);
287
+
288
+ // Get all runs for a project
289
+ const runs = await client.getRuns(projectId);
290
+
291
+ // Add a new run
292
+ const newRun = await client.addRun(projectId, {
293
+ suite_id: suiteId,
294
+ name: 'Automated Test Run',
295
+ include_all: true,
296
+ });
297
+
298
+ // Close a run
299
+ await client.closeRun(runId);
300
+
301
+ // Delete a run
302
+ await client.deleteRun(runId);
303
+ ```
304
+
305
+ ### Tests & Results
306
+
307
+ ```typescript
308
+ // Get test by ID
309
+ const test = await client.getTest(testId);
310
+
311
+ // Get all tests in a run
312
+ const tests = await client.getTests(runId);
313
+
314
+ // Add a test result
315
+ const result = await client.addResult(testId, {
316
+ status_id: 1, // 1 = Passed, 5 = Failed
317
+ comment: 'Test completed successfully',
318
+ elapsed: '2m 30s',
319
+ defects: 'BUG-123',
320
+ });
321
+
322
+ // Add result for a specific case in a run
323
+ const result = await client.addResultForCase(runId, caseId, {
324
+ status_id: 5,
325
+ comment: 'Test failed due to timeout',
326
+ });
327
+
328
+ // Add multiple results at once
329
+ const results = await client.addResultsForCases(runId, {
330
+ results: [
331
+ { case_id: 1, status_id: 1, comment: 'Passed' },
332
+ { case_id: 2, status_id: 5, comment: 'Failed' },
333
+ ],
334
+ });
335
+ ```
336
+
337
+ ### Users & System
338
+
339
+ ```typescript
340
+ // Get user by ID
341
+ const user = await client.getUser(userId);
342
+
343
+ // Get user by email
344
+ const user = await client.getUserByEmail('user@example.com');
345
+
346
+ // Get all users
347
+ const users = await client.getUsers();
348
+
349
+ // Get all statuses
350
+ const statuses = await client.getStatuses();
351
+
352
+ // Get all priorities
353
+ const priorities = await client.getPriorities();
354
+
355
+ // Get milestones
356
+ const milestones = await client.getMilestones(projectId);
357
+ ```
358
+
359
+ ### Caching
360
+
361
+ The client automatically caches GET requests to improve performance:
362
+
363
+ ```typescript
364
+ // First call hits the API
365
+ const project1 = await client.getProject(1);
366
+
367
+ // Second call uses cached result
368
+ const project2 = await client.getProject(1);
369
+
370
+ // Clear cache when needed
371
+ client.clearCache();
372
+ ```
373
+
374
+ The client performs periodic cleanup of expired cache entries automatically. Resources are automatically cleaned up when the Node.js process exits, but you can manually clean up if needed:
375
+
376
+ ```typescript
377
+ // Manual cleanup (usually not needed)
378
+ client.destroy();
379
+
380
+ // The client automatically registers process handlers for cleanup:
381
+ // process.on('exit', cleanupAllClients);
382
+ // process.on('SIGINT', ...);
383
+ // process.on('SIGTERM', ...);
384
+ ```
385
+
386
+ ### Rate Limiting
387
+
388
+ Built-in rate limiting prevents API abuse by enforcing a sliding window limit:
389
+
390
+ ```typescript
391
+ const client = new TestRailClient({
392
+ baseUrl: 'https://example.testrail.io',
393
+ email: 'user@example.com',
394
+ apiKey: 'key',
395
+ rateLimiter: {
396
+ maxRequests: 50, // 50 requests
397
+ windowMs: 30000, // per 30 seconds (default: 100 req / minute)
398
+ },
399
+ });
400
+
401
+ // Requests exceeding limits will throw TestRailApiError with a wait message
402
+ ```
403
+
404
+ ### Security Best Practices
405
+
406
+ The client implements several security best practices to protect your data:
407
+
408
+ - **HTTPS Required**: The client issues a console warning if initialized with an HTTP `baseUrl`. Basic authentication sends credentials in Base64 format, which is not secure over unencrypted HTTP connections. Always use HTTPS in production.
409
+ - **Strict Parameter Validation**: All API methods validate that ID parameters are positive integers. This prevents parameter manipulation and ensures that invalid data is caught before making a network request.
410
+
411
+ ## Development
412
+
413
+ ### Prerequisites
414
+
415
+ - Node.js 20.x or higher
416
+ - npm or yarn
417
+
418
+ ### Setup
419
+
420
+ ```bash
421
+ # Clone the repository
422
+ git clone https://github.com/dichovsky/testrail-api-client.git
423
+ cd testrail-api-client
424
+
425
+ # Install dependencies
426
+ npm install
427
+
428
+ # Run tests
429
+ npm test
430
+
431
+ # Run tests with coverage
432
+ npm run test:coverage
433
+
434
+ # Build the project
435
+ npm run build
436
+
437
+ # Run linting
438
+ npm run lint
439
+
440
+ # Type checking
441
+ npm run typecheck
442
+ ```
443
+
444
+ ### Project Structure
445
+
446
+ ```
447
+ src/
448
+ ├── client.ts # Main TestRail client with advanced features
449
+ ├── types.ts # TypeScript interfaces and type definitions
450
+ ├── utils.ts # Shared utility functions
451
+ └── index.ts # Public API exports
452
+
453
+ tests/
454
+ ├── client.test.ts # Core client functionality tests
455
+ ├── enhanced-features.test.ts # Advanced features tests (caching, rate limiting, retry logic)
456
+ ├── coverage-improvement.test.ts # Additional edge case and validation tests
457
+ ├── index.test.ts # Export and integration tests
458
+ ├── performance.test.ts # Performance and memory tests
459
+ └── types.test.ts # Type definition tests
460
+ ```
461
+
462
+ ## Contributing
463
+
464
+ 1. Fork the repository
465
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
466
+ 3. Make your changes
467
+ 4. Add tests for new functionality
468
+ 5. Run the test suite (`npm test`)
469
+ 6. Run linting (`npm run lint`)
470
+ 7. Commit your changes (`git commit -m 'Add amazing feature'`)
471
+ 8. Push to the branch (`git push origin feature/amazing-feature`)
472
+ 9. Open a Pull Request
473
+
474
+ ### Code Quality
475
+
476
+ This project maintains high code quality standards:
477
+
478
+ - **TypeScript**: Strict mode with comprehensive type checking and interfaces
479
+ - **ESLint**: Extensive rules for code quality, security, and TypeScript best practices
480
+ - **Testing**: 97.6%+ test coverage with 140+ comprehensive test cases
481
+ - **Documentation**: Comprehensive JSDoc comments with parameter validation
482
+ - **Security**: Input validation, error handling, and security-focused linting rules
483
+
484
+ ## License
485
+
486
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
487
+
488
+ ## Changelog
489
+
490
+ ### 1.0.0
491
+
492
+ Initial release with comprehensive TestRail API support and advanced features:
493
+
494
+ **Core Features:**
495
+
496
+ - Full CRUD operations for projects, suites, cases, plans, runs, and results
497
+ - Complete TypeScript support with strict type checking
498
+
499
+ **Performance & Reliability:**
500
+
501
+ - Intelligent caching system for GET requests with automatic cleanup
502
+ - Rate limiting with configurable sliding window
503
+ - Retry logic with exponential backoff for resilient API calls
504
+ - Request timeouts with proper AbortController usage
505
+
506
+ **Security & Validation:**
507
+
508
+ - Comprehensive input validation for all parameters
509
+ - Custom error classes (TestRailApiError, TestRailValidationError)
510
+ - Security warnings for insecure protocols
511
+ - Protection against SSRF, credential exposure, and parameter injection
512
+
513
+ **Developer Experience:**
514
+
515
+ - 97.6%+ test coverage with 456+ test cases
516
+ - Strict ESLint configuration with security rules
517
+ - Comprehensive JSDoc documentation
518
+ - Modern ES2022+ features and async/await throughout
519
+ - Automatic resource cleanup and graceful shutdown handling
520
+
521
+ ## Support
522
+
523
+ - 📖 [Documentation](https://github.com/dichovsky/testrail-api-client#readme)
524
+ - 🐛 [Issues](https://github.com/dichovsky/testrail-api-client/issues)
525
+ - 💬 [Discussions](https://github.com/dichovsky/testrail-api-client/discussions)
526
+
527
+ ## Related Projects
528
+
529
+ - [TestRail API Introduction](https://support.testrail.com/hc/en-us/articles/7077083596436-Introduction-to-the-TestRail-API) - Official API overview
530
+ - [TestRail API Reference](https://support.testrail.com/hc/en-us/articles/7077819069460-Using-the-API) - Full endpoint documentation
531
+ - [TestRail](https://www.testrail.com/) - Test management platform
532
+
533
+ ## Buy Me A Coffee
534
+
535
+ In case you want to support my work
536
+
537
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoffee.com/dichovsky)
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map