> ## Documentation Index
> Fetch the complete documentation index at: https://docs.almedia.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Editor testing — `AlmediaLinkEditorMock`

> The AlmediaLink API — releases before SDK 1.3.0. Synced from the source repository.

Editor-only test hook for driving the SDK into any state (status, error, notifications, in-game reward grants, progress, native log) from a play-mode test or an editor host script. See [Driving non-happy paths](https://docs.almedia.dev/technical/integration-guide/editor-and-play-mode.md#driving-non-happy-paths) in the integration guide for the narrative.

The whole API lives in `AlmediaLink.Editor.Testing` (assembly `AlmediaLink.Editor`, `includePlatforms:["Editor"]`). Host references must be wrapped in `#if UNITY_EDITOR` so they don't reach iOS/Android player compilation.

***

Namespace: `AlmediaLink.Editor.Testing` · static class

The first call to any method here puts the underlying editor mock into **manual mode** for the rest of the play session: every subsequent `Initialize` / `StartLinking` / `FetchNotifications` becomes a no-op so canned coroutines cannot race against test emissions, and any already-scheduled simulate coroutine is cancelled on the flip. Manual mode resets on domain reload.

Every method **throws `InvalidOperationException`** if called before `AlmediaLinkSDK.Initialize` - the throw is deliberate so test ordering bugs surface at test-author time instead of as silent no-ops.

### `static void EmitStatus(AlmediaStatus status, string reason = null, bool? canShowRewardHub = null, bool? canShowOffer = null)`

Delivers a status transition. `CurrentStatus`, `NotAvailableReason`, `ScreenAvailability` and their events reflect it on the same call - no `yield return` required before reading.

`reason` is the raw wire string and is meaningful only with `AlmediaStatus.NotAvailable`: `"holdout"` maps to [`AlmediaNotAvailableReason.Holdout`](https://docs.almedia.dev/technical/api-reference/almedialink/models#almedianotavailablereason), `"disabled"` to `Disabled`, any other string to `Unknown`.

A call that does not pass the availability parameters, e.g. `EmitStatus(AlmediaStatus.Linked)`, gets them defaulted to `true` for `Linked` and `false` for every other status. Pass them explicitly for other shapes:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
// Holdout player.
AlmediaLinkEditorMock.EmitStatus(AlmediaStatus.NotAvailable, "holdout");

// Linking declared in DisabledFeatures - the bundled LinkButton hides.
AlmediaLinkEditorMock.EmitStatus(AlmediaStatus.NotAvailable, "disabled");

// Linked, but the reward hub is gone - the bundled LinkButton hides.
AlmediaLinkEditorMock.EmitStatus(AlmediaStatus.Linked, canShowRewardHub: false, canShowOffer: false);
```

### `static void EmitError(AlmediaErrorCode code, string message)`

Fires `OnErrorOccurred` with the given code and message. Use this to exercise error-handling UI under every entry in [`AlmediaErrorCode`](https://docs.almedia.dev/technical/api-reference/almedialink/models#almediaerrorcode).

### `static void EmitLinkCompleted()`

Fires `OnLinkCompleted` with the current UTC timestamp. Use it to test "celebrate a fresh link" UX in isolation from the linking flow itself.

### `static void EmitNotifications(params MockNotification[] items)`

Fires `OnNotificationsReceived` with the supplied items, converted into the SDK's internal model. Pass no arguments for an empty batch (note: `AlmediaLinkSDK` short-circuits empty batches and does **not** raise `OnNotificationsReceived` - useful for verifying the "no new rewards" branch on the SDK side).

### `static void EmitInGameRewardGrant(params MockInGameReward[] rewards)`

Fires `OnInGameRewardGrantRequested` with a generated grant id and the current UTC timestamp, delivered through the same bridge path the native plugins use. Pass at least one reward; the SDK drops a rewardless grant as malformed, which a bare `EmitInGameRewardGrant()` can exercise.

### `static void EmitInGameRewardGrant(string id, params MockInGameReward[] rewards)`

Same, with an explicit grant id (null or empty generates one). Delivery on device is at-least-once, so call this twice with the same id to reproduce a redelivered grant and verify your dedup:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
var rewards = new[] { new MockInGameReward(250, "gems"), new MockInGameReward(3, "spins") };
AlmediaLinkEditorMock.EmitInGameRewardGrant("grant-1", rewards);
AlmediaLinkEditorMock.EmitInGameRewardGrant("grant-1", rewards);   // must credit once
```

### `static void EmitProgress(AlmediaProgress progress)`

Applies `progress` as the latest snapshot. It uses the same bridge path as the native plugins. `AlmediaLinkSDK.Progress` holds the snapshot and `OnProgressUpdated` fires on the same call. Pass `null` to model the native SDK clearing the snapshot: the accessor becomes `null` and the event fires with `null`. Build a snapshot with the public constructors. Pass a `null` username to model a snapshot that clears the previous username:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
var points = new AlmediaRewardPoints(12500, new AlmediaMoney(11.50m, "EUR"), new AlmediaMoney(12.50m, "USD"));
var task = new AlmediaTask("t-1", AlmediaTaskKind.Burning, "Reach level 10", points, new AlmediaTaskProgress(3, 10),
    DateTimeOffset.UtcNow.AddHours(2).ToString("o"));                          // RewardDropsAt in two hours
AlmediaLinkEditorMock.EmitProgress(new AlmediaProgress("s-1", "2026-09-14T10:00:00.000Z", "demo_player",
    points, points, new[] { task }, new AlmediaCompletedTask[0], new AlmediaTask[0]));
AlmediaLinkEditorMock.EmitProgress(new AlmediaProgress("s-2", "2026-09-14T10:01:00.000Z", null,
    points, points, new[] { task }, new AlmediaCompletedTask[0], new AlmediaTask[0]));   // Username reads null
AlmediaLinkEditorMock.EmitProgress(null);                                          // Progress reads null
```

### `static void EmitTaskCompleted(string id, AlmediaCompletedTask task)`

Fires `OnTaskCompleted`. If `id` is null or empty, the mock generates one. Delivery on a device is best-effort and can repeat. Call this method twice with the same id to reproduce a replay and to test your deduplication.

### `static void EmitBalanceChanged(string id, AlmediaRewardPoints balance, AlmediaRewardPoints change)`

Fires `OnBalanceChanged` with the balance after the change and the signed change. Pass negative coins and negative amounts in `change` to model a reversal.

### `static void EmitScreenPresented(AlmediaScreen screen)`

Fires `OnScreenPresented` for the given screen, without opening a real webview. Pair it with a later `EmitScreenDismissed` for the same screen to reproduce native's matched-pair contract in a test.

### `static void EmitScreenDismissed(AlmediaScreen screen, InAppScreenResultType result, AlmediaErrorCode errorCode = AlmediaErrorCode.Unknown, string errorMessage = null)`

Fires `OnScreenDismissed` for the given screen with the given result. `errorCode` and `errorMessage` apply only to [`InAppScreenResultType.Failed`](https://docs.almedia.dev/technical/api-reference/almedialink/models#inappscreenresulttype) and are ignored for the completed/cancelled outcomes.

### `static void EmitNativeLog(AlmediaLogLevel level, string message)`

Delivers a forwarded log line through the same path the iOS/Android plugins use. Subscribers of `AlmediaLinkSDK.OnLog` receive it as if it had come from the native side.

### `static void CancelPending()`

Stops any pending auto-simulate coroutine. Mostly relevant for tests that want to assert "no callback fires" after `Initialize` - call this immediately after `AlmediaLinkSDK.Initialize` and the scheduled `Eligible` transition never arrives. The first call to any other `Emit*` method calls this internally as part of the manual-mode flip.

***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.