This guide explains the structure and purpose of JSON files used in the integration test framework.
The test framework uses two JSON files for authentication:
| File | Purpose | Lifespan | Git Tracked |
|---|---|---|---|
test_credentials.json |
User credentials for POD login | Permanent | No (git-ignored) |
complete_auth_data.json |
OAuth tokens + RSA keys | 1 hour | No (git-ignored) |
Contains your POD account credentials that Puppeteer uses to automate the login flow. This file is created manually and remains stable.
integration_test/fixtures/test_credentials.json
{
"email": "your-pod-username",
"password": "your-pod-password",
"securityKey": "your-2fa-security-key",
"webId": "https://pods.dev.solidcommunity.au/your-pod/profile/card#me",
"podUrl": "https://pods.dev.solidcommunity.au/your-pod/",
"issuer": "https://pods.dev.solidcommunity.au"
}
| Field | Type | Description | Example |
|---|---|---|---|
email |
string | POD account email/username | "healthpod-test" |
password |
string | POD account password | "SecurePassword123" |
securityKey |
string | Two-factor authentication key | "123456" (if enabled) |
webId |
string | Your Solid WebID (unique identifier) | "https://pods.dev.solidcommunity.au/healthpod-test/profile/card#me" |
podUrl |
string | Root URL of your POD storage | "https://pods.dev.solidcommunity.au/healthpod-test/" |
issuer |
string | OpenID Connect issuer (POD provider) | "https://pods.dev.solidcommunity.au" |
cat > integration_test/fixtures/test_credentials.json <<'EOF'
{
"email": "your-username",
"password": "your-password",
"securityKey": "your-2fa-key",
"webId": "https://pods.dev.solidcommunity.au/your-username/profile/card#me",
"podUrl": "https://pods.dev.solidcommunity.au/your-username/",
"issuer": "https://pods.dev.solidcommunity.au"
}
EOF
CRITICAL: This file contains sensitive credentials and is git-ignored. Never commit it to version control.
# .gitignore already includes:
integration_test/fixtures/test_credentials.json
Contains the complete authentication data structure extracted from a real OAuth login session, including:
This file is automatically generated by the Puppeteer automation and expires after 1 hour.
integration_test/fixtures/complete_auth_data.json
{
"web_id": "https://pods.dev.solidcommunity.au/healthpod-test/profile/card#me",
"logout_url": "https://pods.dev.solidcommunity.au/logout",
"rsa_info": {
"public_key_jwk": {
"kty": "RSA",
"n": "base64-encoded-modulus...",
"e": "AQAB"
},
"private_key_jwk": {
"kty": "RSA",
"n": "base64-encoded-modulus...",
"e": "AQAB",
"d": "base64-encoded-private-exponent...",
"p": "base64-encoded-prime1...",
"q": "base64-encoded-prime2...",
"dp": "base64-encoded-dmp1...",
"dq": "base64-encoded-dmq1...",
"qi": "base64-encoded-iqmp..."
},
"private_key_pem": "-----BEGIN RSA PRIVATE KEY-----\nMIIEow...\n-----END RSA PRIVATE KEY-----",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMIIBIj...\n-----END PUBLIC KEY-----"
},
"auth_response": {
"token": {
"access_token": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6IjEifQ...",
"id_token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ...",
"refresh_token": "nrU_gKrpS9ZTbvLfSt6O3UCCLNdsFPUyuZ2dDzG0bUx",
"token_type": "DPoP",
"expires_at": 1762867910,
"scope": "openid webid offline_access"
},
"client": {
"client_id": "-I5uBOy6NBCfMJUTk2QnJ",
"client_name": "MovieStar E2E Test Client",
"redirect_uris": ["http://localhost:44007/"]
},
"credential": {
"webId": "https://pods.dev.solidcommunity.au/healthpod-test/profile/card#me",
"iss": "https://pods.dev.solidcommunity.au/",
"accessToken": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6IjEifQ...",
"idToken": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ...",
"refreshToken": "nrU_gKrpS9ZTbvLfSt6O3UCCLNdsFPUyuZ2dDzG0bUx",
"tokenType": "DPoP",
"expiresAt": 1762867910
}
}
}
| Field | Description |
|---|---|
web_id |
User’s Solid WebID (copied from auth_response) |
logout_url |
URL to revoke OAuth session |
rsa_info |
RSA keypair in multiple formats for DPoP signing |
auth_response |
Complete OAuth token response and metadata |
| Field | Description |
|---|---|
public_key_jwk |
Public key in JSON Web Key format (shared with POD) |
private_key_jwk |
Private key in JWK format (for solidpod package) |
private_key_pem |
Private key in PEM format (standard encoding) |
public_key_pem |
Public key in PEM format |
| Field | Description | Expiry |
|---|---|---|
access_token |
DPoP-bound token for API requests | 1 hour |
id_token |
JWT containing user identity claims | 1 hour |
refresh_token |
Token to obtain new access tokens | Varies (not always supported) |
token_type |
Always “DPoP” for Solid | N/A |
expires_at |
Unix timestamp when token expires | N/A |
scope |
OAuth scopes granted | N/A |
This file is generated by running:
# Automated (recommended)
dart run integration_test/tools/generate_auth_data.dart
# Or through test auto-regeneration
flutter test integration_test/workflows/pod_favorites_real_test.dart \
-d linux --dart-define=AUTO_REGENERATE=true
The generation process:
test_credentials.jsonOAuth access tokens expire after 3600 seconds (1 hour). When tokens expire, you’ll see:
OpenIdException(invalid_grant): grant request is invalid
Solutions:
Auto-regeneration (recommended for local testing):
await CredentialInjector.injectFullAuth(autoRegenerateOnFailure: true);
Manual regeneration:
dart run integration_test/tools/generate_auth_data.dart
Pre-generate for CI (see Testing Guide)
stateDiagram-v2
[*] --> NotGenerated: Initial state
NotGenerated --> Fresh: Run generate_auth_data.dart
Fresh --> Expired: Wait 1 hour
Expired --> Fresh: Regenerate tokens
Fresh --> InUse: Test loads complete_auth_data.json
InUse --> TestPass: Token valid
InUse --> TestFail: Token expired
TestFail --> Fresh: Auto-regenerate (if enabled)
| Aspect | test_credentials.json | complete_auth_data.json |
|---|---|---|
| Contains | User credentials | OAuth tokens + RSA keys |
| Created by | Developer (manual) | Puppeteer automation |
| Lifespan | Permanent | 1 hour |
| Used by | Puppeteer login script | Test credential injection |
| Regeneration | Never (unless password changes) | Every hour or on-demand |
| Format | Simple key-value pairs | Complex nested structure |
flowchart LR
A[test_credentials.json] --> B[Puppeteer Automation]
B --> C[OAuth Login Flow]
C --> D[Generate RSA Keys]
D --> E[Exchange for Tokens]
E --> F[complete_auth_data.json]
F --> G[CredentialInjector]
G --> H[FlutterSecureStorage]
H --> I[Integration Tests]
Error:
Exception: Test credentials file not found: integration_test/fixtures/test_credentials.json
Solution: Create test_credentials.json as described above.
Error:
FormatException: Unexpected character
Solution: Validate JSON syntax with:
cat integration_test/fixtures/test_credentials.json | jq .
Error:
OpenIdException(invalid_grant)
Solution: Regenerate complete_auth_data.json:
dart run integration_test/tools/generate_auth_data.dart
Error:
NoSuchMethodError: The getter 'rsa_info' was called on null
Cause: File was manually edited or generated with old tool version.
Solution: Delete and regenerate:
rm integration_test/fixtures/complete_auth_data.json
dart run integration_test/tools/generate_auth_data.dart