@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 +21 -0
- package/README.md +686 -0
- package/assets/favicon.ico +0 -0
- package/bin/jasmine +1053 -0
- package/bin/testify +4640 -0
- package/esm-loader.mjs +332 -0
- package/lib/index.js +231 -0
- package/package.json +89 -0
- package/postinstall.mjs +161 -0
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
|