Skip to content

Commit 39bf30d

Browse files
laurigatesclaude
andcommitted
feat: implement real integration testing with FoundryVTT containers
Replace mock-heavy integration tests with real FoundryVTT instances using testcontainers and felddy/foundryvtt-docker. This addresses critical test quality issues identified in the existing test suite. Features: - Real FoundryVTT container integration via testcontainers - GitHub Actions CI/CD with Docker services - Contract testing to validate API response schemas - Authentication and WebSocket testing with real instances - Comprehensive error scenario coverage - Security-conscious fork PR handling with manual approval Technical Implementation: - Added testcontainers dependency for programmatic container management - Created vitest.integration.config.ts for integration test configuration - Implemented docker-compose.test.yml using proven community container - Added credential management templates for secure testing - Created comprehensive integration test suite in tests/integration/ - Added GitHub Actions workflow with real FoundryVTT services This replaces implementation detail testing with behavior validation, ensuring tests verify actual FoundryVTT integration rather than mock responses. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent dbbfc9f commit 39bf30d

File tree

12 files changed

+2202
-68
lines changed

12 files changed

+2202
-68
lines changed

.env.test.template

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# FoundryVTT Test Environment Variables
2+
# Copy this file to .env.test and fill in your actual credentials
3+
4+
# FoundryVTT Authentication - Required for downloading the software
5+
FOUNDRY_USERNAME=your-foundry-username
6+
FOUNDRY_PASSWORD=your-foundry-password
7+
FOUNDRY_LICENSE_KEY=your-foundry-license-key
8+
9+
# Test Configuration
10+
FOUNDRY_TEST_URL=http://localhost:30001
11+
FOUNDRY_ADMIN_KEY=test-admin-key-123
12+
13+
# Logging
14+
LOG_LEVEL=warn
15+
FOUNDRY_LOG_LEVEL=warn

.github/workflows/integration.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Integration Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
workflow_dispatch:
9+
10+
env:
11+
NODE_VERSION: '20'
12+
13+
jobs:
14+
integration-tests:
15+
name: FoundryVTT Integration Tests
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 30
18+
19+
# Use environment for manual approval on forks (security)
20+
environment:
21+
name: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'requires-approval' || 'auto-approved' }}
22+
23+
services:
24+
foundryvtt:
25+
image: felddy/foundryvtt:release
26+
ports:
27+
- 30001:30000
28+
env:
29+
FOUNDRY_HOSTNAME: 0.0.0.0
30+
FOUNDRY_LOCAL_HOSTNAME: localhost
31+
FOUNDRY_ADMIN_KEY: test-admin-key-123
32+
FOUNDRY_USERNAME: ${{ secrets.FOUNDRY_USERNAME }}
33+
FOUNDRY_PASSWORD: ${{ secrets.FOUNDRY_PASSWORD }}
34+
FOUNDRY_LICENSE_KEY: ${{ secrets.FOUNDRY_LICENSE_KEY }}
35+
FOUNDRY_LOG_LEVEL: warn
36+
CONTAINER_VERBOSE: false
37+
FOUNDRY_MINIFY_STATIC_FILES: true
38+
FOUNDRY_UPNP: false
39+
FOUNDRY_DEMO_MODE: false
40+
options: >-
41+
--health-cmd "curl -f http://localhost:30000 || exit 1"
42+
--health-interval 10s
43+
--health-timeout 5s
44+
--health-retries 12
45+
--health-start-period 60s
46+
47+
steps:
48+
- name: Checkout code
49+
uses: actions/checkout@v4
50+
51+
- name: Setup Node.js
52+
uses: actions/setup-node@v4
53+
with:
54+
node-version: ${{ env.NODE_VERSION }}
55+
cache: 'npm'
56+
57+
- name: Install dependencies
58+
run: npm ci
59+
60+
- name: Build project
61+
run: npm run build
62+
63+
- name: Wait for FoundryVTT to be ready
64+
run: |
65+
echo "Waiting for FoundryVTT to be fully ready..."
66+
timeout 180 bash -c 'until curl -f http://localhost:30001 >/dev/null 2>&1; do
67+
echo "Waiting for FoundryVTT...";
68+
sleep 5;
69+
done'
70+
echo "FoundryVTT is ready!"
71+
72+
- name: Verify FoundryVTT health
73+
run: |
74+
curl -f http://localhost:30001 || (echo "FoundryVTT health check failed" && exit 1)
75+
76+
- name: Run integration tests
77+
env:
78+
FOUNDRY_URL: http://localhost:30001
79+
FOUNDRY_ADMIN_KEY: test-admin-key-123
80+
LOG_LEVEL: warn
81+
run: npm run test:integration
82+
timeout-minutes: 15
83+
84+
- name: Upload test results
85+
if: always()
86+
uses: actions/upload-artifact@v4
87+
with:
88+
name: integration-test-results
89+
path: |
90+
test-results/
91+
coverage/
92+
retention-days: 7
93+
94+
# Optional: Run integration tests with Docker Compose locally
95+
integration-tests-compose:
96+
name: Docker Compose Integration Tests
97+
runs-on: ubuntu-latest
98+
timeout-minutes: 20
99+
if: github.event_name == 'workflow_dispatch'
100+
101+
steps:
102+
- name: Checkout code
103+
uses: actions/checkout@v4
104+
105+
- name: Setup Node.js
106+
uses: actions/setup-node@v4
107+
with:
108+
node-version: ${{ env.NODE_VERSION }}
109+
cache: 'npm'
110+
111+
- name: Install dependencies
112+
run: npm ci
113+
114+
- name: Build project
115+
run: npm run build
116+
117+
- name: Create test environment file
118+
run: |
119+
cp .env.test.template .env.test
120+
echo "FOUNDRY_USERNAME=${{ secrets.FOUNDRY_USERNAME }}" >> .env.test
121+
echo "FOUNDRY_PASSWORD=${{ secrets.FOUNDRY_PASSWORD }}" >> .env.test
122+
echo "FOUNDRY_LICENSE_KEY=${{ secrets.FOUNDRY_LICENSE_KEY }}" >> .env.test
123+
124+
- name: Run Docker Compose integration tests
125+
run: npm run test:integration:docker
126+
127+
- name: Upload Docker Compose test results
128+
if: always()
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: docker-compose-test-results
132+
path: |
133+
test-results/
134+
coverage/
135+
retention-days: 7

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,8 @@ data/
105105
# Test files
106106
test-results/
107107
playwright-report/
108+
109+
# Integration test secrets and data
110+
secrets.json
111+
tests/fixtures/foundry-data/
112+
.env.test

docker-compose.test.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
version: '3.8'
2+
3+
services:
4+
foundryvtt:
5+
image: felddy/foundryvtt:release
6+
container_name: foundryvtt-test
7+
hostname: foundryvtt-test
8+
ports:
9+
- "30001:30000"
10+
environment:
11+
# FoundryVTT configuration
12+
- FOUNDRY_HOSTNAME=0.0.0.0
13+
- FOUNDRY_LOCAL_HOSTNAME=localhost
14+
- FOUNDRY_ROUTE_PREFIX=
15+
- FOUNDRY_SSL_CERT=
16+
- FOUNDRY_SSL_KEY=
17+
- FOUNDRY_PROXY_SSL=false
18+
- FOUNDRY_PROXY_PORT=443
19+
- FOUNDRY_AWS_CONFIG=false
20+
- FOUNDRY_WORLD=test-world
21+
- FOUNDRY_ADMIN_KEY=test-admin-key-123
22+
- FOUNDRY_MINIFY_STATIC_FILES=true
23+
- FOUNDRY_UPNP=false
24+
- FOUNDRY_DEMO_MODE=false
25+
26+
# Authentication (use secrets in CI)
27+
- FOUNDRY_USERNAME=${FOUNDRY_USERNAME:-}
28+
- FOUNDRY_PASSWORD=${FOUNDRY_PASSWORD:-}
29+
- FOUNDRY_LICENSE_KEY=${FOUNDRY_LICENSE_KEY:-}
30+
31+
# Logging
32+
- FOUNDRY_LOG_LEVEL=warn
33+
- CONTAINER_VERBOSE=false
34+
volumes:
35+
# Mount test data directory
36+
- type: bind
37+
source: ./tests/fixtures/foundry-data
38+
target: /data
39+
# Mount any test modules/systems
40+
- type: bind
41+
source: ./tests/fixtures/modules
42+
target: /data/Data/modules
43+
read_only: true
44+
healthcheck:
45+
test: ["CMD", "curl", "-f", "http://localhost:30000"]
46+
interval: 5s
47+
timeout: 3s
48+
retries: 12
49+
start_period: 30s
50+
restart: "no"
51+
52+
networks:
53+
default:
54+
name: foundryvtt-test-network

0 commit comments

Comments
 (0)