For each Hook, prove two things: the handler returns the expected typed result, and M3UAndroid applies that result in the feature that calls it.
Keep parsing, mapping, and validation in ordinary Kotlin functions. Unit-test those functions with request fixtures and assert the exact result object.
Cover at least:
- the smallest valid request;
- empty and boundary values;
- an expected server or validation failure;
- cancellation during long-running work;
- a missing required setting or credential handle.
Use handleResult(...) or handleResultWithBroker(...) for expected failures. Reserve thrown exceptions for unexpected faults.
The API 1 golden wire fixtures contain invocation and result envelopes, every current Hook request and result, and broker messages. Run their decode-and-re-encode checks with:
./gradlew :extension:api:jvmTestBefore changing a fixture, use the
compatibility decision table.
Keep every previous schema fixture and add a sibling schema-<version> directory.
For the Hello module:
./gradlew :samples:hello-extension:assembleDebugUse the corresponding task for your extension module.
Run the current extension build with M3UAndroid, then use the feature that owns the Hook.
| Hook | Acceptance result |
|---|---|
settings.schema.contribute |
The settings page renders the returned sections and reloads saved values. |
search.provider.query |
Returned stable references promote matching visible channels in phone search. |
metadata.channel.enrich |
A generic provider refresh applies patches only to channels in the request. |
epg.content.refresh |
A refresh imports returned programmes; a failed call preserves the previous contribution. |
background.task.run |
Enabling the extension schedules each declaration. Disabling it cancels the work. A network task waits for a connection. |
| Provider discover and validate | Discover returns one descriptor. The form uses its schema. Valid input completes host-managed authentication. |
| Provider refresh | The account is saved only after initial refresh succeeds. The imported playlist contains the complete snapshot. |
| Provider playback and close | A same-origin source plays with host-resolved headers. Stopping playback closes the remote session. |
The reference provider test covers discovery, rejected and successful login, initial and later refresh, playback resolution, header resolution, and session close through the external transport.
For each Hook, trigger one expected failure and confirm:
- the extension returns a stable
ExtensionError.code; recoverablematches whether repeating the same call can succeed;- no partly valid result is applied;
- cancellation stops long-running work.
For a broker-backed Hook, also confirm that an approved origin works, an unapproved origin and
cross-origin redirect fail. Missing network must be rejected; when a request uses a credential
handle, missing credential.read must also be rejected.
Provider tests should also cover rejected credentials, a failed refresh that preserves stored data, an invalid playback result, and repeated session close.
- Keep the same extension identity and signing certificate.
- Confirm existing settings still load.
- Confirm removed or renamed fields reconcile as intended.
- Confirm a new required capability prompts for authorization.
- Confirm diagnostics contain no secrets, credential handles, or user-identifying request and response data.
Next: prepare a release or update.