equinor / equinor/fusion-framework
FrameworkMockConfigurator: real enableX helpers can silently un-mock a pinned module
- Dominant language
- TypeScript
- Stars
- 10
- Forks
- 10
- Avg merge
- 19h 40m
- Merged PRs (30d)
- 150
Description
## Problem
`FrameworkMockConfigurator._pin` wraps a built-in module's `configure` factory so it always returns the same instance, then registers it via `this.addConfig({ module: pinned })`. `ModulesConfigurator.addConfig` re-registers modules by name on a last-write-wins basis: when a later `addConfig` call arrives for the same module name (e.g. an application calling the module's *real* `enableX`/`configureX` helper — not its mock-specific counterpart — against a `FrameworkMockConfigurator`), it removes the pinned module's callbacks and installs the real, unpinned `configure` factory instead.
The result: initialization builds a fresh, real (unmocked) configurator instance for that module, while the corresponding accessor on `FrameworkMockConfigurator` (e.g. `.telemetry`, `.msal`, `.http`) keeps returning the stale pinned mock — configuration and reads silently drift apart.
This affects every module pinned by `FrameworkMockConfigurator`: `msal`, `serviceDiscovery`, `http`, `services`, `context`, and `telemetry`.
## Reproduction sketch
```typescript
const fusion = await mockFramework((configurator) => {
// enableTelemetry is the REAL helper, not enableTelemetryMock
enableTelemetry(configurator, (builder) => builder.setMetadata({ app: 'demo' }));
});
// configurator.telemetry.adapter still refers to the pinned mock,
// but fusion.modules.telemetry is now backed by a real, unmocked configurator.
```
## Discussion
Raised as a [review comment](https://github.com/equinor/fusion-framework/pull/5246#discussion_r3748647630) on #5246. A fix was drafted there (a `#pinnedDescriptors` map plus an `addConfig` override redirecting same-name registrations back to the pinned descriptor) but reverted as too much bookkeeping for a single-PR fix, since this is a pre-existing, generic risk of the `_pin` mechanism rather than something specific to the telemetry mock.
## Suggested direction
Fix this once, generically, in `FrameworkMockConfigurator`/`_pin` (or in `ModulesConfigurator.addConfig`'s re-registration semantics) rather than per-module. Whatever shape it takes, add a regression test that calls a built-in module's real `enableX` helper against `FrameworkMockConfigurator` and asserts the pinned accessor still reflects the mock after initialization.
Contributor guide
Research direction
Start in FrameworkMockConfigurator._pin and ModulesConfigurator.addConfig, then trace how same-name registrations replace pinned callbacks. Add a regression test using a built-in module’s real enableX/configureX helper with FrameworkMockConfigurator; done means initialization preserves the pinned mock and its accessor stays consistent with the module instance.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100