forked from AdguardTeam/HostlistCompiler
-
Notifications
You must be signed in to change notification settings - Fork 0
testing
Jayson Knight edited this page Jan 13, 2026
·
1 revision
This project has comprehensive unit test coverage using Deno's native testing framework. All tests are co-located with source files in the src/ directory.
Tests follow the pattern: *.test.ts files are placed next to their corresponding source files.
Example:
src/cli/
├── ArgumentParser.ts
├── ArgumentParser.test.ts ← Test file
├── ConfigurationLoader.ts
└── ConfigurationLoader.test.ts ← Test file
# Run all tests
deno task test
# Run tests with coverage
deno task test:coverage
# Run tests in watch mode
deno task test:watch
# Run specific test file
deno test src/cli/ArgumentParser.test.ts
# Run tests for a specific module
deno test src/transformations/
# Run tests with permissions
deno test --allow-read --allow-write --allow-net --allow-env --unstable-kv- ✅
ArgumentParser.ts- Argument parsing and validation (22 tests) - ✅
ConfigurationLoader.ts- JSON loading and validation (16 tests) - ✅
OutputWriter.ts- File writing (8 tests)
- ✅
FilterCompiler.ts- Main compilation logic (existing tests) - ✅
HeaderGenerator.ts- Header generation (16 tests)
- ✅
ConditionalEvaluator.ts- Boolean expression evaluation (25 tests) - ✅
ContentFetcher.ts- HTTP/file fetching (18 tests) - ✅
FilterDownloader.ts- Filter list downloading (existing tests) - ✅
PreprocessorEvaluator.ts- Directive processing (23 tests)
- ✅
CompressTransformation.ts- Hosts to adblock conversion - ✅
ConvertToAsciiTransformation.ts- Unicode to ASCII conversion - ✅
DeduplicateTransformation.ts- Remove duplicate rules - ✅
ExcludeTransformation.ts- Pattern-based exclusion (10 tests) - ✅
IncludeTransformation.ts- Pattern-based inclusion (11 tests) - ✅
InsertFinalNewLineTransformation.ts- Final newline insertion - ✅
InvertAllowTransformation.ts- Allow rule inversion - ✅
RemoveCommentsTransformation.ts- Comment removal - ✅
RemoveEmptyLinesTransformation.ts- Empty line removal - ✅
RemoveModifiersTransformation.ts- Modifier removal - ✅
TrimLinesTransformation.ts- Whitespace trimming - ✅
ValidateTransformation.ts- Rule validation - ✅
TransformationRegistry.ts- Transformation management (13 tests)
- ✅
Benchmark.ts- Performance benchmarking (existing tests) - ✅
EventEmitter.ts- Event emission (existing tests) - ✅
logger.ts- Logging functionality (17 tests) - ✅
RuleUtils.ts- Rule parsing utilities (existing tests) - ✅
StringUtils.ts- String utilities (existing tests) - ✅
TldUtils.ts- Domain/TLD parsing (36 tests) - ✅
Wildcard.ts- Wildcard pattern matching (existing tests)
- ✅
ConfigurationValidator.ts- Configuration validation (existing tests)
- ✅
platform.test.ts- Platform abstractions (existing tests)
- ✅
NoSqlStorage.test.ts- Storage operations (existing tests)
- Total Test Files: 32
- Total Modules Tested: 40+
- Test Cases: 500+
- Coverage: High coverage on all core functionality
import { assertEquals, assertExists, assertRejects } from '@std/assert';
import { MyClass } from './MyClass.ts';
Deno.test('MyClass - should do something', () => {
const instance = new MyClass();
const result = instance.doSomething();
assertEquals(result, expectedValue);
});
Deno.test('MyClass - should handle errors', async () => {
const instance = new MyClass();
await assertRejects(
async () => await instance.failingMethod(),
Error,
'Expected error message',
);
});- Co-locate tests - Place test files next to source files
-
Use descriptive names -
MyClass - should do something specific - Test edge cases - Empty inputs, null values, boundary conditions
- Use mocks - Mock external dependencies (file system, HTTP)
- Keep tests isolated - Each test should be independent
- Use async/await - For asynchronous operations
- Clean up - Remove temporary files/state after tests
class MockFileSystem implements IFileSystem {
private files: Map<string, string> = new Map();
setFile(path: string, content: string) {
this.files.set(path, content);
}
async readTextFile(path: string): Promise<string> {
return this.files.get(path) ?? '';
}
async writeTextFile(path: string, content: string): Promise<void> {
this.files.set(path, content);
}
async exists(path: string): Promise<boolean> {
return this.files.has(path);
}
}class MockHttpClient implements IHttpClient {
private responses: Map<string, Response> = new Map();
setResponse(url: string, response: Response) {
this.responses.set(url, response);
}
async fetch(url: string): Promise<Response> {
return this.responses.get(url) ?? new Response('', { status: 404 });
}
}const mockLogger = {
debug: () => {},
info: () => {},
warn: () => {},
error: () => {},
};Tests are automatically run on:
- Push to main branch
- Pull requests
- Pre-deployment
Generate coverage reports:
# Generate coverage
deno task test:coverage
# View coverage report
deno coverage coverage --htmlMake sure to run with required permissions:
deno test --allow-read --allow-write --allow-net --allow-env --unstable-kvIncrease timeout for slow operations:
Deno.test({
name: 'slow operation',
fn: async () => {
// test code
},
sanitizeOps: false,
sanitizeResources: false,
});Ensure mocks are passed to constructors:
const mockFs = new MockFileSystem();
const instance = new MyClass(mockFs); // Pass mock