diff --git a/docs/technical-reference/fml/fml-spec.mdx b/docs/technical-reference/fml/fml-spec.mdx index 58ba46d8e..e6f0df79f 100644 --- a/docs/technical-reference/fml/fml-spec.mdx +++ b/docs/technical-reference/fml/fml-spec.mdx @@ -160,6 +160,132 @@ FxNimbus.features.appMenu.recordExposure() > The user is exposed to the hamburger menu icon every time the toolbar is shown, but the menu items only when the menu is opened. > This would suggest that the hamburger menu icon needs to be specified in a different feature, e.g. the `toolbar` feature. +For [co-enrolling features](/technical-reference/fml/coenrolling-features), you must specify which experiment the exposure is for: + + + + +```swift +FxNimbus.shared.features.messaging.recordExperimentExposure(slug) +``` + + + + +```kotlin +FxNimbus.features.messaging.recordExperimentExposure(slug) +``` + + + + +### Reporting malformed configuration + +If your app detects that a feature configuration from an experiment is invalid, you can report it as telemetry. The `partId` parameter identifies which part of the configuration is malformed. + + + + +```swift +FxNimbus.shared.features.newtab.recordMalformedConfiguration(partId: "invalid-card") +``` + + + + +```kotlin +FxNimbus.features.newtab.recordMalformedConfiguration(partId = "invalid-card") +``` + + + + +### Getting the JSON representation + +You can get the raw JSON representation of a feature's configuration with `toJSONObject()`: + + + + +```swift +let json = FxNimbus.shared.features.newtab.toJSONObject() +``` + + + + +```kotlin +val json = FxNimbus.features.newtab.toJSONObject() +``` + + + + +### Testing with hardcoded values + +Each feature holder provides testing methods to inject values directly, without a running Nimbus SDK: + + + + +```swift +// Inject a hardcoded configuration for testing +FxNimbus.shared.features.newtab.withCachedValue(myTestConfig) + +// Check if running under test +if FxNimbus.shared.features.newtab.isUnderTest() { + // skip network calls, etc. +} +``` + + + + +```kotlin +// Inject a hardcoded configuration for testing +FxNimbus.features.newtab.withCachedValue(myTestConfig) + +// Check if running under test +if (FxNimbus.features.newtab.isUnderTest()) { + // skip network calls, etc. +} +``` + + + + +Available testing methods: +- **`withCachedValue(value)`** — overwrite the cached configuration with a test value. +- **`withInitializer(create)`** — change how `Variables` are mapped to the feature object (clears cache). +- **`withSdk(getSdk)`** — reset the SDK connection (clears cache). +- **`isUnderTest()`** — returns `true` when the SDK is a `HardcodedNimbusFeatures` instance. + +See the [Android integration guide](/platform-guides/android/integration#unit-and-ui-testing-with-hardcodednimbusfeatures) for a complete testing example using `HardcodedNimbusFeatures`. + ### Identifier cases All the examples below use `kebab-case` for identifiers. When these identifiers are used to generate code, they are transformed to the language-specific casing. For example, a feature is specified in the FML as being called `spotlight-search`, but would be referred to in Swift as `spotlightSearch`.