AnisurgeAnisurge / extensions

Testing Extensions — Validation, Smoke Tests, and Debugging

Comprehensive testing guide for Anisurge .asx extension packs — schema validation, deep link installation testing, playback smoke tests, update verification, and troubleshooting common issues.

Testing Extensions — Validation, Smoke Tests & Debugging

This guide covers everything from automated schema validation to manual smoke tests for verifying that an .asx extension pack installs correctly and produces working video streams.

Schema Validation

The official validate.mjs script checks all pack files for structural correctness:

node scripts/validate.mjs

What It Checks

CheckDescriptionError Example
JSON syntaxAll .asx files must be valid JSONUnexpected token at line 3
schemaVersionMust equal 1Expected schemaVersion 1, got 2
id formatMust match [a-z0-9-]+ID "My_Cool_Pack!" contains invalid characters
versionCodeMust be a positive integerversionCode must be a positive integer
Pipeline completenessAt least one step, must end with map.videosPipeline must end with map.videos step
Step field validationRequired fields present and correct typehttp.get step missing required 'url' field
Unknown fieldsNo unrecognized top-level fieldsUnknown field: 'pipeline.resolve.0.randomField'
Index consistencyIndex entries match pack filesPack 'anokoto' has version 1.0.1 but index says 1.0.0

Running Validation

# Validate all packs and index
node scripts/validate.mjs

# Regenerate index.json from packs (run after adding/modifying packs)
node scripts/generate-index.mjs

# Validate again after regenerating
node scripts/validate.mjs

On Android (Build ≥ 140)

  1. Host the .asx file at an HTTPS URL (raw GitHub URLs work well: https://raw.githubusercontent.com/<user>/<repo>/main/extensions/<id>/<id>.asx)

  2. Generate the install deep link:

anisurgex://extensions/install?type=source&engine=ANISURGE&url=<URL>&name=<NAME>&version=<VERSION>
  1. Open on device — tap the link or paste it into a browser address bar
  2. Confirm installation in the app dialog
  3. Check Extensions list — the pack should appear under installed sources

Install Confirmation Dialog

The app shows a dialog with:

  • Pack name and version
  • Engine type (ANISURGE)
  • Download URL
  • Icon (if iconUrl provided)
  • Confirm and Cancel buttons

On confirm, ExtensionManager.install() runs:

  1. Detects .asx extension → calls installAsxPack()
  2. Downloads the .asx file to a staging path
  3. Parses and validates the file content via AsxPackParser.parsePack()
  4. Writes the validated pack to {dataDir}/anisurge/{id}/extension.asx
  5. Updates the installed sources list

Testing Repository Install

For repository-level testing:

anisurgex://extensions/install?type=repo&engine=ANISURGE&url=<INDEX_URL>&name=<REPO_NAME>

The app adds the index URL as a repository, fetches the pack list, and shows available packs.

Playback Smoke Tests

After installation, verify the pack produces working streams:

Basic Playback Test

  1. Open any anime with a known AniList ID that maps to your source
  2. On the Watch screen, select your extension from the server selector
  3. If the pack declares subDub: true, verify both language options
  4. Tap play and observe:
    • Video loads within 10 seconds
    • Audio plays in sync with video
    • Player controls respond (play/pause, seek, volume)

Additional Checks

Test CaseExpected ResultHow to Test
Valid AniList + episodeAt least one video URL returnedPlay any episode of a known anime
Dub when claimedDub track plays without errorsToggle to Dub in server selector
SubtitlesSubtitles appear on screenEnable subtitles in player if supported
Missing mappingClear error, no app crashTry an AniList ID that doesn't exist in the source
Corrupt packInstall rejected with error messageModify the .asx to have invalid JSON, attempt install
Network error during fetchGraceful fallback or timeout errorDisconnect network, attempt playback
Multiple episodesEach episode resolves correctlyPlay episode 1, then episode 12
Intro/outro skipSkip button appears at correct timesIf pack provides intro/outro timestamps
Session resumePlayback resumes from last positionStart episode, seek to midpoint, close, reopen

Update Testing

To verify the auto-update mechanism:

  1. Install the pack at versionCode 1
  2. Bump versionCode to 2 (and version string) in the .asx and index.json
  3. Regenerate index: node scripts/generate-index.mjs
  4. Push changes to the repository
  5. Refresh the app's Extensions list (pull down or tap Refresh)
  6. Verify: the pack shows an Update badge
  7. Tap Update: the app re-downloads and replaces the pack
  8. Verify: version displays as the new version

Troubleshooting

"Failed to install" Error

CauseSolution
Invalid JSON syntaxRun node scripts/validate.mjs to detect syntax errors
schemaVersion ≠ 1Set "schemaVersion": 1
id contains invalid charactersUse only [a-z0-9-] characters
versionCode missing or zeroSet a positive integer (start at 1)
Pipeline missing map.videosAdd { "step": "map.videos", "file": "...", ... } as final step
Network error downloading .asxVerify the URL is accessible over HTTPS

"No streams found" Error

CauseSolution
Provider API changedInspect the current provider response with browser dev tools
Rate limitingAdd delay between requests or use try branches for fallbacks
Region blockingTest with VPN or proxy
Incorrect variable path in map.videosCheck {{sources.sources.file}} matches actual JSON structure
Headers missing (Referer, User-Agent)Add required headers to map.videos.headers
AniList ID not found in sourceTest with a known popular anime ID (e.g., 21 for One Piece)

Playback Issues

SymptomPossible CauseCheck
Black screen with audioCDN requires specific Referer/Origin headersAdd headers to map.videos.headers
Video stuttersHLS segments too large or CDN throttlingTry a different quality or server
Subtitles not showingSubtitle URL incorrect or CORS blockedVerify subtitle URL directly in browser
Wrong episode loadsEpisode number mapping differs (0-indexed vs 1-indexed)Check provider's episode numbering
App crashes on playbackM3U8 format not supported or corrupt segmentsTest the M3U8 URL in VLC/mpv desktop

Debugging Tools

Browser DevTools

Most providers serve HTML or JSON that you can inspect:

curl -H "User-Agent: Mozilla/5.0" "https://provider.example.com/api/21/1" | jq .

Testing Without the App

You can simulate the pipeline manually using curl and jq:

# Step 1: http.get
curl -s "https://provider.example.com/api/21/1" -o response.json

# Step 2: json.parse + json.get
cat response.json | jq '.sources[0].file'

# Step 3: verify the stream URL works
ffprobe "$(cat response.json | jq -r '.sources[0].file')" 2>&1 | head -5

Logcat (Android Debug)

Monitor deep link handling on Android:

adb logcat -s Anisurge:D *:S | grep -E "deepLink|extension|Deeplink"

Pack Validation Checklist

Before submitting a pull request, verify:

  • node scripts/validate.mjs passes without errors
  • Pack installs via deep link on Android build ≥ 140
  • At least one episode plays successfully with video and audio
  • Sub and Dub both tested (if subDub: true)
  • versionCode incremented for any behavior change
  • index.json regenerated with node scripts/generate-index.mjs
  • No hardcoded API keys, tokens, or private URLs
  • nsfw: true if content requires age restriction
  • Icon included (optional but recommended)