@@ -4,12 +4,38 @@ TypeScript-based integration tests for the awf (Agentic Workflow Firewall) CLI.
44
55## Overview
66
7- This directory contains integration tests that verify firewall behavior across multiple scenarios:
7+ This directory contains comprehensive integration tests that verify firewall behavior across multiple scenarios. Currently includes ** 17 integration test files ** covering :
88
9- - ** Volume Mounts Tests** (` integration/volume-mounts.test.ts ` ) - Custom volume mount functionality
10- - ** Container Workdir Tests** (` integration/container-workdir.test.ts ` ) - Container working directory handling
11- - ** Docker Warning Tests** (` integration/docker-warning.test.ts ` ) - Docker warning functionality
12- - ** No Docker Tests** (` integration/no-docker.test.ts ` ) - Testing without Docker available
9+ ### Core Functionality
10+ - ** Basic Firewall Functionality** (` basic-firewall.test.ts ` ) - Domain whitelisting, subdomain matching, exit code propagation
11+ - ** Exit Code Propagation** (` exit-code-propagation.test.ts ` ) - Comprehensive exit code handling tests
12+ - ** Container Working Directory** (` container-workdir.test.ts ` ) - Container workdir configuration
13+
14+ ### Domain & Pattern Matching
15+ - ** Blocked Domains** (` blocked-domains.test.ts ` ) - Domain blocking and precedence
16+ - ** Wildcard Patterns** (` wildcard-patterns.test.ts ` ) - Wildcard pattern matching (* .domain.com)
17+
18+ ### Security
19+ - ** Network Security** (` network-security.test.ts ` ) - Capability restrictions, bypass prevention, SSRF protection
20+ - ** Robustness Tests** (` robustness.test.ts ` ) - Edge cases, protocol handling, security corners
21+
22+ ### Configuration
23+ - ** DNS Servers** (` dns-servers.test.ts ` ) - DNS server configuration and resolution
24+ - ** Environment Variables** (` environment-variables.test.ts ` ) - Environment variable passing
25+ - ** Volume Mounts** (` volume-mounts.test.ts ` ) - Volume mount configuration
26+
27+ ### Protocol & Network
28+ - ** Protocol Support** (` protocol-support.test.ts ` ) - HTTP/HTTPS, HTTP/2, IPv4/IPv6
29+ - ** Git Operations** (` git-operations.test.ts ` ) - Git clone, fetch, ls-remote
30+
31+ ### Error Handling & Logging
32+ - ** Error Handling** (` error-handling.test.ts ` ) - Network errors, command failures, recovery
33+ - ** Log Commands** (` log-commands.test.ts ` ) - Log parsing and analysis
34+
35+ ### Integration Testing
36+ - ** Claude Code** (` claude-code.test.ts ` ) - Claude Code CLI integration
37+ - ** No Docker** (` no-docker.test.ts ` ) - Docker-in-Docker removal verification
38+ - ** Docker Warning** (` docker-warning.test.ts ` ) - Docker command warning messages
1339
1440## Smoke Tests
1541
@@ -28,20 +54,34 @@ These smoke tests use the locally built firewall and validate:
2854
2955```
3056tests/
31- ├── integration/ # Integration test suites
32- │ ├── volume-mounts.test.ts
57+ ├── integration/ # Integration test suites (17 files)
58+ │ ├── basic-firewall.test.ts
59+ │ ├── blocked-domains.test.ts
60+ │ ├── claude-code.test.ts
3361│ ├── container-workdir.test.ts
62+ │ ├── dns-servers.test.ts
3463│ ├── docker-warning.test.ts
35- │ └── no-docker.test.ts
36- ├── fixtures/ # Reusable test utilities
37- │ ├── cleanup.ts # Docker resource cleanup
38- │ ├── awf-runner.ts # Execute awf commands
39- │ ├── docker-helper.ts # Docker operations
40- │ ├── log-parser.ts # Parse Squid/iptables logs
41- │ └── assertions.ts # Custom Jest matchers
64+ │ ├── environment-variables.test.ts
65+ │ ├── error-handling.test.ts
66+ │ ├── exit-code-propagation.test.ts
67+ │ ├── git-operations.test.ts
68+ │ ├── log-commands.test.ts
69+ │ ├── network-security.test.ts
70+ │ ├── no-docker.test.ts
71+ │ ├── protocol-support.test.ts
72+ │ ├── robustness.test.ts
73+ │ ├── volume-mounts.test.ts
74+ │ └── wildcard-patterns.test.ts
75+ ├── fixtures/ # Reusable test utilities
76+ │ ├── cleanup.ts # Docker resource cleanup
77+ │ ├── awf-runner.ts # Execute awf commands
78+ │ ├── docker-helper.ts # Docker operations
79+ │ ├── log-parser.ts # Parse Squid/iptables logs
80+ │ └── assertions.ts # Custom Jest matchers
4281├── setup/
43- │ └── jest.integration.config.js # Jest configuration
44- └── README.md # This file
82+ │ ├── jest.integration.config.js # Jest configuration
83+ │ └── jest.setup.ts # Test setup
84+ └── README.md # This file
4585```
4686
4787## Running Tests
@@ -223,14 +263,41 @@ Key considerations:
223263- Cleanup runs before and after tests to prevent resource leaks
224264- Artifacts (logs, reports) are collected on failure
225265
226- ## Smoke Tests
266+ ## Test Suite
267+
268+ The project uses TypeScript-based integration tests that run in CI via ` .github/workflows/test-coverage.yml ` :
227269
228- Comprehensive firewall testing is done via agentic workflow smoke tests:
270+ ** Integration test files (17 total):**
271+ | Category | Test File | Description |
272+ | ----------| -----------| -------------|
273+ | Core | ` basic-firewall.test.ts ` | Domain whitelisting, connectivity |
274+ | Core | ` exit-code-propagation.test.ts ` | Exit code handling |
275+ | Core | ` container-workdir.test.ts ` | Container working directory |
276+ | Domains | ` blocked-domains.test.ts ` | Domain blocking |
277+ | Domains | ` wildcard-patterns.test.ts ` | Wildcard matching |
278+ | Security | ` network-security.test.ts ` | Capability restrictions, SSRF |
279+ | Security | ` robustness.test.ts ` | Edge cases, bypass prevention |
280+ | Config | ` dns-servers.test.ts ` | DNS configuration |
281+ | Config | ` environment-variables.test.ts ` | Environment variables |
282+ | Config | ` volume-mounts.test.ts ` | Volume mounts |
283+ | Protocol | ` protocol-support.test.ts ` | HTTP/HTTPS, HTTP/2 |
284+ | Protocol | ` git-operations.test.ts ` | Git over HTTPS |
285+ | Errors | ` error-handling.test.ts ` | Error scenarios |
286+ | Logging | ` log-commands.test.ts ` | Log parsing |
287+ | Integration | ` claude-code.test.ts ` | Claude Code CLI |
288+ | Integration | ` no-docker.test.ts ` | Docker removal |
289+ | Integration | ` docker-warning.test.ts ` | Docker warnings |
229290
230- - ` .github/workflows/smoke-claude.md ` - Claude engine smoke tests
231- - ` .github/workflows/smoke-copilot.md ` - Copilot engine smoke tests
291+ ** Smoke test workflows:**
292+ - ` .github/workflows/smoke-claude.md ` - Claude engine validation (uses locally built firewall)
293+ - ` .github/workflows/smoke-codex.md ` - Codex engine validation (uses locally built firewall)
294+ - ` .github/workflows/smoke-copilot.md ` - Copilot engine validation (uses locally built firewall)
232295
233- These smoke tests build and test the firewall locally, validating end-to-end functionality.
296+ ** CI workflow:**
297+ - All tests run with ` sudo -E ` for iptables manipulation
298+ - Tests run serially to avoid Docker resource conflicts
299+ - Automatic cleanup before and after test runs
300+ - Test logs uploaded as artifacts on failure
234301
235302## Troubleshooting
236303
@@ -265,20 +332,89 @@ docker pull alpine:latest
265332docker pull dannydirect/tinyproxy:latest
266333```
267334
268- ## Test Suite
335+ ## Testing Patterns and Best Practices
269336
270- The project uses TypeScript-based integration tests that run in CI via ` .github/workflows/test-coverage.yml ` :
337+ ### 1. Test Structure
271338
272- ** Integration test suites:**
273- - ` tests/integration/volume-mounts.test.ts ` - Custom volume mount functionality
274- - ` tests/integration/container-workdir.test.ts ` - Container working directory handling
339+ Each test file follows a consistent structure:
275340
276- ** Smoke test workflows:**
277- - ` .github/workflows/smoke-claude.md ` - Claude engine validation (uses locally built firewall)
278- - ` .github/workflows/smoke-copilot.md ` - Copilot engine validation (uses locally built firewall)
341+ ``` typescript
342+ /// <reference path = " ../jest-custom-matchers.d.ts" />
279343
280- ** CI workflow:**
281- - All tests run with ` sudo -E ` for iptables manipulation
282- - Tests run serially to avoid Docker resource conflicts
283- - Automatic cleanup before and after test runs
284- - Test logs uploaded as artifacts on failure
344+ import { describe , test , expect , beforeAll , afterAll } from ' @jest/globals' ;
345+ import { createRunner , AwfRunner } from ' ../fixtures/awf-runner' ;
346+ import { cleanup } from ' ../fixtures/cleanup' ;
347+
348+ describe (' Feature Name' , () => {
349+ let runner: AwfRunner ;
350+
351+ beforeAll (async () => {
352+ await cleanup (false ); // Clean up before tests
353+ runner = createRunner ();
354+ });
355+
356+ afterAll (async () => {
357+ await cleanup (false ); // Clean up after tests
358+ });
359+
360+ test (' should do something' , async () => {
361+ const result = await runner .runWithSudo (' command' , {
362+ allowDomains: [' github.com' ],
363+ logLevel: ' debug' ,
364+ timeout: 60000 ,
365+ });
366+
367+ expect (result ).toSucceed ();
368+ }, 120000 ); // Set individual test timeout
369+ });
370+ ```
371+
372+ ### 2. Use Custom Matchers
373+
374+ ``` typescript
375+ // Check success/failure
376+ expect (result ).toSucceed ();
377+ expect (result ).toFail ();
378+
379+ // Check specific exit code
380+ expect (result ).toExitWithCode (0 );
381+ expect (result ).toExitWithCode (42 );
382+
383+ // Check timeout
384+ expect (result ).toTimeout ();
385+ ```
386+
387+ ### 3. Handle Timeouts
388+
389+ - Set reasonable timeouts for each test (typically 120000ms for integration tests)
390+ - Use ` --max-time ` with curl to prevent indefinite hangs
391+ - Set ` timeout ` in runner options
392+
393+ ### 4. Clean Up Resources
394+
395+ - Always run ` cleanup(false) ` in ` beforeAll ` and ` afterAll `
396+ - Use ` keepContainers: true ` only when needed for log inspection
397+ - Clean up manually created files in ` afterEach `
398+
399+ ### 5. Avoid Flaky Tests
400+
401+ - Use explicit timeouts with network commands
402+ - Don't depend on timing-sensitive conditions
403+ - Use ` || true ` or error handling for expected failures
404+ - Test for specific exit codes, not just success/failure
405+
406+ ### 6. Group Related Tests
407+
408+ ``` typescript
409+ describe (' Feature Category' , () => {
410+ describe (' Subsection A' , () => {
411+ test (' scenario 1' , ... );
412+ test (' scenario 2' , ... );
413+ });
414+
415+ describe (' Subsection B' , () => {
416+ test (' scenario 3' , ... );
417+ test (' scenario 4' , ... );
418+ });
419+ });
420+ ```
0 commit comments