@epikodelabs/testify 1.0.16

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 Oleksii Shepel
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,686 @@
1
+ # testify
2
+
3
+ A flexible test runner for Jasmine that supports multiple execution environments with built-in TypeScript compilation, hot module reloading, and code coverage.
4
+
5
+ ## Features
6
+
7
+ - **Multiple Execution Environments**
8
+ - Real browsers (Chrome, Firefox, Safari) for DOM and browser API testing
9
+ - Headless browsers for CI/CD pipelines
10
+ - Node.js for fastest unit test execution
11
+
12
+ - **Developer Experience**
13
+ - Hot Module Reload (HMR) for instant test feedback
14
+ - TypeScript compilation with source maps
15
+ - Interactive browser-based test reporter
16
+ - VS Code debug integration
17
+
18
+ - **Testing Capabilities**
19
+ - Istanbul code coverage reporting
20
+ - Configurable test execution order and randomization
21
+ - Cross-environment test compatibility
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ # Install the test runner
29
+ npm install --save-dev @epikodelabs/testify
30
+
31
+ # Optional: Install Playwright for browser testing
32
+ npx playwright install
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Quick Start
38
+
39
+ ### 1. Initialize Configuration
40
+
41
+ ```bash
42
+ npx testify init
43
+ ```
44
+
45
+ This creates `testify.json` with sensible defaults:
46
+
47
+ ```json
48
+ {
49
+ "srcDirs": ["./src"],
50
+ "testDirs": ["./tests"],
51
+ "outDir": "./dist/.vite-jasmine-build",
52
+ "browser": "chrome",
53
+ "headless": false,
54
+ "port": 8888,
55
+ "coverage": false
56
+ }
57
+ ```
58
+
59
+ ### 2. Write Jasmine Tests
60
+
61
+ Create `.spec.ts` files in your test directory:
62
+
63
+ ```typescript
64
+ // tests/calculator.spec.ts
65
+ import { Calculator } from '../src/calculator';
66
+
67
+ describe('Calculator', () => {
68
+ let calc: Calculator;
69
+
70
+ beforeEach(() => {
71
+ calc = new Calculator();
72
+ });
73
+
74
+ it('should add two numbers', () => {
75
+ expect(calc.add(2, 3)).toBe(5);
76
+ });
77
+
78
+ it('should work with browser APIs', () => {
79
+ if (typeof window !== 'undefined') {
80
+ expect(window.location).toBeDefined();
81
+ }
82
+ });
83
+ });
84
+ ```
85
+
86
+ ### 3. Run Your Tests
87
+
88
+ ```bash
89
+ # Development: Interactive browser mode
90
+ npx testify
91
+
92
+ # CI/CD: Headless Chrome
93
+ npx testify --headless
94
+
95
+ # Fastest: Direct Node.js execution
96
+ npx testify --headless --browser node
97
+
98
+ # With code coverage
99
+ npx testify --coverage
100
+
101
+ # Watch mode with HMR
102
+ npx testify --watch
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Execution Modes
108
+
109
+ ### Browser Mode (Default)
110
+
111
+ **Best for:** Development and debugging
112
+
113
+ ```bash
114
+ npx testify
115
+ ```
116
+
117
+ - Opens `http://localhost:8888` in your default browser
118
+ - Interactive HTML test reporter with Jasmine UI
119
+ - Full browser DevTools for debugging
120
+ - Access to DOM, localStorage, fetch, and all browser APIs
121
+
122
+ ### Headless Browser Mode
123
+
124
+ **Best for:** CI/CD and automated testing
125
+
126
+ ```bash
127
+ # Chrome (default)
128
+ npx testify --headless
129
+
130
+ # Firefox
131
+ npx testify --headless --browser firefox
132
+
133
+ # Safari/WebKit
134
+ npx testify --headless --browser webkit
135
+ ```
136
+
137
+ - Runs real browser without UI
138
+ - Full browser API support
139
+ - Console output with test results
140
+ - Excellent for cross-browser testing
141
+
142
+ ### Node.js Mode
143
+
144
+ **Best for:** Fast unit testing
145
+
146
+ ```bash
147
+ npx testify --headless --browser node
148
+ ```
149
+
150
+ - Fastest execution (no browser startup overhead)
151
+ - Limited to Node.js APIs only
152
+ - Perfect for pure TypeScript logic
153
+ - No DOM or browser-specific APIs
154
+
155
+ **Suppress console output:**
156
+ ```bash
157
+ # Using CLI flags
158
+ npx testify --headless --browser node --silent
159
+ npx testify --headless --browser node --quiet
160
+
161
+ # Or in testify.json
162
+ {
163
+ "suppressConsoleLogs": true
164
+ }
165
+
166
+ # Or via environment variable
167
+ TS_TEST_RUNNER_SUPPRESS_CONSOLE_LOGS=1 npx testify --headless --browser node
168
+ ```
169
+
170
+ ### Watch Mode
171
+
172
+ **Best for:** Rapid development iteration
173
+
174
+ ```bash
175
+ npx testify --watch
176
+ ```
177
+
178
+ - Hot Module Reload for instant feedback
179
+ - Watches source and test files for changes
180
+ - Automatically re-runs affected tests
181
+ - Only works in headed browser mode
182
+ - WebSocket-based synchronization
183
+
184
+ **Important:** Watch mode cannot be combined with `--headless` or `--coverage`.
185
+
186
+ ---
187
+
188
+ ## Code Coverage
189
+
190
+ Enable Istanbul code coverage with the `--coverage` flag:
191
+
192
+ ```bash
193
+ npx testify --coverage
194
+ ```
195
+
196
+ **How it works:**
197
+ - Source files are instrumented using `istanbul-lib-instrument` during preprocessing
198
+ - Coverage data is collected while tests run
199
+ - Reports are generated using `istanbul-lib-report` and `istanbul-reports`
200
+
201
+ **Output formats:**
202
+ - HTML report: `coverage/index.html`
203
+ - LCOV format: `coverage/lcov.info`
204
+ - Text summary in console
205
+
206
+ **Note:** Coverage cannot be used with `--watch` mode.
207
+
208
+ ---
209
+
210
+ ## Configuration Reference
211
+
212
+ ### Configuration File: `testify.json`
213
+
214
+ ```json
215
+ {
216
+ // Source and test directories
217
+ "srcDirs": ["./src/lib"],
218
+ "testDirs": ["./src/tests"],
219
+ "exclude": ["**/node_modules/**", "**/.git/**"],
220
+
221
+ // Build output
222
+ "outDir": "./dist/.vite-jasmine-build",
223
+ "preserveOutputs": false,
224
+
225
+ // Execution settings
226
+ "browser": "chrome",
227
+ "headless": false,
228
+ "port": 8888,
229
+ "coverage": false,
230
+ "watch": false,
231
+ "suppressConsoleLogs": false,
232
+
233
+ // TypeScript configuration
234
+ "tsconfig": "tsconfig.json",
235
+
236
+ // Jasmine configuration
237
+ "jasmineConfig": {
238
+ "env": {
239
+ "random": true,
240
+ "seed": 0,
241
+ "timeout": 120000,
242
+ "stopSpecOnExpectationFailure": false
243
+ }
244
+ },
245
+
246
+ // HTML page customization
247
+ "htmlOptions": {
248
+ "title": "My Project Tests"
249
+ },
250
+
251
+ // Vite build options
252
+ "viteBuildOptions": {
253
+ "target": "es2022",
254
+ "sourcemap": true,
255
+ "minify": false
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### Configuration Options
261
+
262
+ | Option | Type | Default | Description |
263
+ |--------|------|---------|-------------|
264
+ | `srcDirs` | `string[]` | `["./src"]` | Source code directories |
265
+ | `testDirs` | `string[]` | `["./tests"]` | Test file directories |
266
+ | `exclude` | `string[]` | `["**/node_modules/**"]` | Patterns to exclude |
267
+ | `outDir` | `string` | `"./dist/.vite-jasmine-build"` | Build output directory |
268
+ | `browser` | `string` | `"chrome"` | Browser to use: `chrome`, `firefox`, `webkit`, `node` |
269
+ | `headless` | `boolean` | `false` | Run in headless mode |
270
+ | `port` | `number` | `8888` | Development server port |
271
+ | `coverage` | `boolean` | `false` | Enable code coverage |
272
+ | `watch` | `boolean` | `false` | Enable watch mode with HMR |
273
+ | `suppressConsoleLogs` | `boolean` | `false` | Hide spec-level console output in Node mode |
274
+ | `preserveOutputs` | `boolean` | `false` | Skip regenerating outputs when they exist |
275
+
276
+ ---
277
+
278
+ ## Command Line Reference
279
+
280
+ ### Basic Commands
281
+
282
+ | Command | Description |
283
+ |---------|-------------|
284
+ | `npx testify` | Run in browser (development mode) |
285
+ | `npx testify init` | Create configuration file |
286
+ | `npx testify --help` | Show help message |
287
+
288
+ ### Execution Flags
289
+
290
+ | Flag | Description |
291
+ |------|-------------|
292
+ | `--headless` | Run in headless mode |
293
+ | `--browser <n>` | Choose browser: `chrome`, `firefox`, `webkit`, `node` |
294
+ | `--watch` | Enable watch mode with HMR |
295
+ | `--coverage` | Generate code coverage reports |
296
+ | `--seed <number>` | Set randomization seed |
297
+ | `--silent` / `--quiet` | Suppress console logs (Node mode only) |
298
+ | `--preserve` | Skip regenerating outputs when they exist |
299
+ | `--config <path>` | Use custom config file |
300
+
301
+ ### Examples
302
+
303
+ ```bash
304
+ # Development workflow
305
+ npx testify --watch
306
+
307
+ # CI/CD pipeline
308
+ npx testify --headless --coverage
309
+
310
+ # Cross-browser testing
311
+ npx testify --headless --browser firefox
312
+ npx testify --headless --browser webkit
313
+
314
+ # Deterministic test order
315
+ npx testify --seed 12345
316
+
317
+ # Fast unit tests with clean console
318
+ npx testify --headless --browser node --silent
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Environment-Specific Testing
324
+
325
+ ### Browser-Only Tests
326
+
327
+ ```typescript
328
+ describe('Browser APIs', () => {
329
+ beforeEach(() => {
330
+ if (typeof window === 'undefined') {
331
+ pending('Browser-only test');
332
+ }
333
+ });
334
+
335
+ it('should test localStorage', () => {
336
+ localStorage.setItem('test', 'value');
337
+ expect(localStorage.getItem('test')).toBe('value');
338
+ localStorage.removeItem('test');
339
+ });
340
+
341
+ it('should test DOM manipulation', () => {
342
+ const div = document.createElement('div');
343
+ div.textContent = 'Hello World';
344
+ document.body.appendChild(div);
345
+
346
+ expect(document.querySelector('div')?.textContent).toBe('Hello World');
347
+
348
+ document.body.removeChild(div);
349
+ });
350
+ });
351
+ ```
352
+
353
+ ### Node.js-Only Tests
354
+
355
+ ```typescript
356
+ describe('Node.js APIs', () => {
357
+ beforeEach(() => {
358
+ if (typeof process === 'undefined') {
359
+ pending('Node.js-only test');
360
+ }
361
+ });
362
+
363
+ it('should access process information', () => {
364
+ expect(process.version).toMatch(/^v\d+/);
365
+ expect(process.platform).toBeDefined();
366
+ });
367
+
368
+ it('should access file system', async () => {
369
+ const fs = await import('fs/promises');
370
+ const stats = await fs.stat(__filename);
371
+ expect(stats.isFile()).toBe(true);
372
+ });
373
+ });
374
+ ```
375
+
376
+ ### Cross-Environment Tests
377
+
378
+ ```typescript
379
+ describe('Universal Code', () => {
380
+ it('should work in any environment', () => {
381
+ const result = myPureFunction('input');
382
+ expect(result).toBe('processed input');
383
+ });
384
+
385
+ it('should detect environment correctly', () => {
386
+ const isBrowser = typeof window !== 'undefined';
387
+ const isNode = typeof process !== 'undefined';
388
+
389
+ expect(isBrowser || isNode).toBe(true);
390
+ });
391
+ });
392
+ ```
393
+
394
+ ---
395
+
396
+ ## Single Spec Runner (jasmine)
397
+
398
+ Run a single spec file in Node.js using `jasmine-core`:
399
+
400
+ ```bash
401
+ # JavaScript specs
402
+ npx jasmine --spec ./tests/example.spec.js
403
+
404
+ # TypeScript specs (recommended)
405
+ node --loader @epikodelabs/testify/esm-loader.mjs \
406
+ ./node_modules/@epikodelabs/testify/bin/jasmine \
407
+ --spec ./tests/example.spec.ts
408
+ ```
409
+
410
+ ### VS Code Debug Configuration
411
+
412
+ Create or update `.vscode/launch.json`:
413
+
414
+ ```bash
415
+ npx jasmine init
416
+ ```
417
+
418
+ Or manually add this configuration:
419
+
420
+ ```json
421
+ {
422
+ "type": "node",
423
+ "request": "launch",
424
+ "name": "Debug current spec (jasmine)",
425
+ "runtimeExecutable": "node",
426
+ "runtimeArgs": [
427
+ "--loader",
428
+ "@epikodelabs/testify/esm-loader.mjs",
429
+ "--enable-source-maps"
430
+ ],
431
+ "program": "${workspaceFolder}/node_modules/@epikodelabs/testify/bin/jasmine",
432
+ "args": ["--spec", "${file}"],
433
+ "cwd": "${workspaceFolder}",
434
+ "console": "integratedTerminal",
435
+ "skipFiles": ["<node_internals>/**"]
436
+ }
437
+ ```
438
+
439
+ **Important:** Do not point at `node_modules/.bin/jasmine` (shell shim). Always use the full path to the actual JS file.
440
+
441
+ ### jasmine Options
442
+
443
+ ```bash
444
+ npx jasmine --spec <path> # Path to spec file
445
+ npx jasmine --random # Randomize test order
446
+ npx jasmine --seed <number> # Set random seed
447
+ npx jasmine --stop-on-fail # Stop on first failure
448
+ npx jasmine --help # Show help
449
+ npx jasmine init # Create VS Code debug config
450
+ ```
451
+
452
+ ---
453
+
454
+ ## CI/CD Integration
455
+
456
+ ### GitHub Actions Example
457
+
458
+ ```yaml
459
+ name: Tests
460
+ on: [push, pull_request]
461
+
462
+ jobs:
463
+ test:
464
+ runs-on: ubuntu-latest
465
+
466
+ steps:
467
+ - uses: actions/checkout@v4
468
+
469
+ - uses: actions/setup-node@v4
470
+ with:
471
+ node-version: '20'
472
+
473
+ - run: npm ci
474
+
475
+ - name: Install Playwright browsers
476
+ run: npx playwright install --with-deps
477
+
478
+ - name: Run Node.js tests (fast)
479
+ run: npx testify --headless --browser node
480
+
481
+ - name: Run Chrome tests with coverage
482
+ run: npx testify --headless --browser chrome --coverage
483
+
484
+ - name: Run Firefox tests
485
+ run: npx testify --headless --browser firefox
486
+
487
+ - name: Upload coverage
488
+ uses: codecov/codecov-action@v3
489
+ with:
490
+ files: ./coverage/lcov.info
491
+ ```
492
+
493
+ ### Performance Comparison
494
+
495
+ | Environment | Speed | Browser APIs | Use Case |
496
+ |-------------|-------|-------------|----------|
497
+ | Node.js | ⚡ Fastest | ❌ None | Unit tests, pure logic |
498
+ | Headless Chrome | 🐌 Medium | ✅ Full | Integration tests, DOM |
499
+ | Headless Firefox | 🐌 Medium | ✅ Full | Cross-browser testing |
500
+ | Browser (headed) | 🐌 Slowest | ✅ Full + DevTools | Development, debugging |
501
+
502
+ ---
503
+
504
+ ## Project Structure
505
+
506
+ The test runner expects this structure (all paths are configurable):
507
+
508
+ ```
509
+ your-project/
510
+ ├── src/
511
+ │ ├── lib/ # Source code
512
+ │ │ ├── calculator.ts
513
+ │ │ └── utils.ts
514
+ │ └── tests/ # Test files
515
+ │ ├── calculator.spec.ts
516
+ │ └── utils.spec.ts
517
+ ├── dist/
518
+ │ └── .vite-jasmine-build/ # Compiled output (auto-generated)
519
+ │ ├── index.html
520
+ │ ├── test-runner.js
521
+ │ └── *.js
522
+ ├── coverage/ # Coverage reports (auto-generated)
523
+ │ ├── index.html
524
+ │ └── lcov.info
525
+ ├── testify.json # Configuration file
526
+ └── tsconfig.json # TypeScript configuration
527
+ ```
528
+
529
+ ---
530
+
531
+ ## Troubleshooting
532
+
533
+ ### Browser Not Found
534
+
535
+ ```bash
536
+ # Install all browsers
537
+ npx playwright install
538
+
539
+ # Or install specific browser
540
+ npx playwright install chrome
541
+ npx playwright install firefox
542
+ npx playwright install webkit
543
+ ```
544
+
545
+ ### Port Already in Use
546
+
547
+ Change the port in `testify.json`:
548
+
549
+ ```json
550
+ {
551
+ "port": 3000
552
+ }
553
+ ```
554
+
555
+ Or use a different port via command line:
556
+
557
+ ```bash
558
+ # Note: Currently requires config file change
559
+ # CLI port override coming in future version
560
+ ```
561
+
562
+ ### No Tests Found
563
+
564
+ Verify:
565
+ - Test files are in the `testDirs` location
566
+ - Files have `.spec.ts` or `.spec.js` extension
567
+ - Tests use proper Jasmine syntax (`describe`, `it`, `expect`)
568
+ - Directories are not in the `exclude` list
569
+
570
+ ### TypeScript Compilation Errors
571
+
572
+ 1. Check your `tsconfig.json` matches your project structure
573
+ 2. Ensure `tsconfig` path in `testify.json` is correct
574
+ 3. Verify path aliases are properly configured
575
+ 4. Check that all dependencies are installed
576
+
577
+ ### Watch Mode Not Working
578
+
579
+ Remember:
580
+ - Watch mode only works in headed browser mode
581
+ - Cannot use with `--headless` flag
582
+ - Cannot use with `--coverage` flag
583
+ - Cannot use with `--browser node`
584
+
585
+ ### Coverage Reports Missing
586
+
587
+ Ensure:
588
+ - `--coverage` flag is used
589
+ - Tests complete successfully
590
+ - Output directory (`coverage/`) has write permissions
591
+ - Not using `--watch` mode (coverage disabled in watch mode)
592
+
593
+ ---
594
+
595
+ ## Comparison with Other Test Runners
596
+
597
+ | Feature | testify | Jest | Vitest | Karma |
598
+ |---------|---------------|------|--------|-------|
599
+ | Real browser testing | ✅ | ❌ | ❌ | ✅ |
600
+ | Node.js execution | ✅ | ✅ | ✅ | ❌ |
601
+ | Hot Module Reload | ✅ | ✅ | ✅ | ❌ |
602
+ | TypeScript support | ✅ | ✅ | ✅ | ⚠️ Plugin |
603
+ | Code coverage | ✅ | ✅ | ✅ | ✅ |
604
+ | Setup complexity | Low | Medium | Low | High |
605
+ | Jasmine framework | ✅ | ❌ | ❌ | ✅ |
606
+ | Active maintenance | ✅ | ✅ | ✅ | ⚠️ Limited |
607
+
608
+ **Why choose testify:**
609
+ - **vs Jest:** Better real browser testing support, actual browser environments
610
+ - **vs Vitest:** Established Jasmine ecosystem, simpler for existing Jasmine users
611
+ - **vs Karma:** Modern tooling, TypeScript-first, simpler setup, active development
612
+
613
+ ---
614
+
615
+ ## Advanced Configuration
616
+
617
+ ### Custom Vite Configuration
618
+
619
+ You can extend the Vite configuration in `testify.json`:
620
+
621
+ ```json
622
+ {
623
+ "viteConfig": {
624
+ "plugins": [],
625
+ "resolve": {
626
+ "alias": {
627
+ "@components": "/src/components"
628
+ }
629
+ }
630
+ }
631
+ }
632
+ ```
633
+
634
+ ### TypeScript Path Mapping
635
+
636
+ Path aliases from `tsconfig.json` are automatically resolved:
637
+
638
+ ```json
639
+ // tsconfig.json
640
+ {
641
+ "compilerOptions": {
642
+ "baseUrl": ".",
643
+ "paths": {
644
+ "@/*": ["src/*"],
645
+ "@tests/*": ["tests/*"]
646
+ }
647
+ }
648
+ }
649
+ ```
650
+
651
+ ### Multiple Source Directories
652
+
653
+ ```json
654
+ {
655
+ "srcDirs": ["./src/lib", "./src/utils", "./src/components"],
656
+ "testDirs": ["./tests/unit", "./tests/integration"]
657
+ }
658
+ ```
659
+
660
+ ### Exclude Patterns
661
+
662
+ ```json
663
+ {
664
+ "exclude": [
665
+ "**/node_modules/**",
666
+ "**/.git/**",
667
+ "**/dist/**",
668
+ "**/coverage/**",
669
+ "**/*.d.ts"
670
+ ]
671
+ }
672
+ ```
673
+
674
+ ---
675
+
676
+ ## License
677
+
678
+ MIT © 2025
679
+
680
+ ---
681
+
682
+ ## Support
683
+
684
+ - **Issues:** [GitHub Issues](https://github.com/epikodelabs/testify/issues)
685
+ - **Documentation:** [GitHub Wiki](https://github.com/epikodelabs/testify/wiki)
686
+ - **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
Binary file