feat(mvux): advanced mocking & previews — spec 013 + implementation (WIP) (backport #3165) - #3176
Open
mergify[bot] wants to merge 19 commits into
Open
feat(mvux): advanced mocking & previews — spec 013 + implementation (WIP) (backport #3165)#3176mergify[bot] wants to merge 19 commits into
mergify[bot] wants to merge 19 commits into
Conversation
Restored state = end of discussion (lost commits 8d589d9 -> 292fb5f ->
2618def -> cd4c9ad), merged from local recovery notes + David's VS Code
copies (his architecture.md was the most recent, post-2618def).
- spec.md: 3 tiers, real VM + real Model with null-injected services,
derived feeds survive via Model-feed cache swap anchor, external
mocking generator (consumer test project), D1-D9 decision log,
open question: context-wide scope / ambient MockingService.Enable()
- architecture.md: seams, swap anchor, MVUX gen (analysis + dependency
attributes + hidden typed hooks) vs Mocking gen (metadata-driven
{Model}Mock/Create/SetModel), tier-1 authorable plain-CLR MessageEntry
(not a DependencyObject, not observable) with first-class custom axes,
natural feed evolution contract, XAML examples
- implementation.md: package split, attribute shapes, hidden hooks,
typed vocabulary, diagnostics FEED3201-3203/MOCK0001, P0 canaries
(derived-swap gate, null-inject, identity matrix, context spike),
test plan, docs plan
- history.md: full version/decision chronology of the spec discussion
(cherry picked from commit d72a52c)
- spec.md: audience/deliverable split, derived-feeds-survive flow, three-tier layering, generator responsibility split, end-to-end sequence, tier-1 evolution sequence; risks and decision log as tables; status header cleaned for team/CEO review (history stays in history.md) - architecture.md: swap-anchor mermaid in section 1, end-to-end ASCII flow replaced by a sequence diagram in section 5 (cherry picked from commit 49c37d3)
(cherry picked from commit cc4a510)
…he swap fail hard Records the decision to drop the dedicated static flag in favour of a per-context bit, and to reuse the hot-reload reflection driver with strict failure instead of best effort. (cherry picked from commit 51c791c)
Adds a per-context bit inherited at creation and reads it where the wrap is decided, so only contexts created under an activation scope wrap their feeds and a live application pays nothing. (cherry picked from commit 57c8d73)
Classifies every feed member as service dependent, derived or independent, and instruments the constructors so an eagerly dereferenced service is reported. The metadata is what the consumer generator reads. (cherry picked from commit a5ed1d0)
Commands have no hot-swap state, so a dedicated seam reassigns the command property after construction. Construction itself needs no seam: the public constructors plus the ambient scope are enough. (cherry picked from commit 007e88c)
Adds the activation scope, the swap engine and the typed feed vocabulary used by the generated mocks. (cherry picked from commit 5852d9b)
The consumer generator reads the app metadata and emits the mock record, the Create factories and the SetModel facade. StateImpl always implements IHotSwapState, so the previous type test never rejected a non-wrapped feed and the swap silently did nothing. Added CanHotSwap and made the engine throw when a mocked feed is not swappable. (cherry picked from commit f4f5aff)
Adds Value, Empty, Undefined, Loading, Error and Refreshing for both scalar feeds and list feeds, built on pinned messages and strongly typed end to end. (cherry picked from commit 6510bbc)
…cabulary The generated record exposes Empty with every input pinned to its empty state, Create() builds from it, and commands can be overridden through the view-model seam. (cherry picked from commit 90aea90)
Logs what landed for the tier 2 and 3 implementation and what is left out of scope. (cherry picked from commit 7cd1650)
The mocked feed vocabulary already exists in Uno.HotTesting.Reactive, so the duplicate assembly is removed and everything lives there: FeedMock and ListFeedMock are reused, CommandMock is added, and the swap engine moves into MockingService as strongly typed helpers. The consumer generator becomes Uno.HotTesting.Reactive.Generator and emits raw string literals. The MVUX instrumentation is now emitted by default, with an assembly level opt-out. (cherry picked from commit fb88e5a)
…ourceContext The ambient activation state is a mocking concern, not a Core one. MockingService now owns the AsyncLocal and registers a probe; SourceContext only keeps the per-instance IsMockingActive bit. In a live application the probe is never registered, so the bit stays false and the cost is zero. (cherry picked from commit fa1d928)
Extended the reactive testing reference with the generated tier 2 and 3 layer, and added a
named catalog sample together with its test. The generated factory class is now named
{Vm}Mock and Empty moved onto the record.
(cherry picked from commit 73b05a5)
… Create
Review feedback: the generated {Vm}Mock is now partial so applications can extend it with
named catalogs, SetModel is renamed to SetMock, Create only takes the mock record,
{Model}Mock.Empty stays on the record so it composes with `with`, and Create opens the
MockingService.Enable() scope itself so user code never has to.
Command mocking is deferred to a future version: the consumer generator no longer emits a
command member nor the __Mock_SetCommand wiring.
(cherry picked from commit ba05821)
Applied: combined the nested if in ViewModelGenTool_3.Mocking, projected ctor.DeclaringSyntaxReferences, SimpleNameSyntax and the accesses with Select, and filtered the nested types and the references explicitly in FeedsMockGenerator. Declined, each answered in its thread: the readonly suggestion on Disposable._onDispose is a false positive (the field is a ref argument of Interlocked.Exchange), the == false simplification targets a bool? whose three-state semantics are intentional, and the Where suggestion filters a computed value. (cherry picked from commit 29714cd)
The repository enables GenerateDocumentationFile together with TreatWarningsAsErrors, so a public member without an XML comment fails the Release build even though a local Debug build stays green. Added /// <inheritdoc /> on FeedsMockGenerator.Initialize and Execute, the same way FeedsGenerator already does. Also fixed MD032, MD012, MD022 and MD031 on the four spec 013 documents. (cherry picked from commit 149b987)
Everything pushed to GitHub must be in English. The spec 013 history document was written in French during the design discussions, which failed the CI spell-checking validation (333 unknown words). spec.md, architecture.md and the reference doc were already clean. - history.md fully translated to English, keeping every SHA, type name, file path and decision id unchanged. - implementation.md: replaced three coined words the dictionary rejects (bikesheddable, Authorable, mockability) with plain English equivalents. Verified with the exact CI commands: cspell over 236 markdown files reports 0 issue, and markdownlint reports no violation. (cherry picked from commit 4a3e1b3)
4 tasks
dr1rrb
approved these changes
Sep 4, 2026
Author
|
Tick the box to add this pull request to the merge queue (same as
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Draft PR tracking the "Advanced MVUX mocking & previews" work.
Lands Spec 013 – MVUX Mocking & Previews (design under
specs/013-mvux-mocking-previews/) and will carry the implementation on top.Kept as draft until the implementation is in.
Scope
MessageEntryCLR type in CoreRelated
Closes #3150
Depends on #3149 (per issue, should land first)
This is an automatic backport of pull request #3165 done by [Mergify](https://mergify.com).