Skip to content

feat: operation tags and list sorting - #134

Open
MaxMichel2 wants to merge 3 commits into
feat/networkmock-request-body-matchingfrom
feat/networkmock-tags-and-sorting
Open

MaxMichel2 wants to merge 3 commits into
feat/networkmock-request-body-matchingfrom
feat/networkmock-tags-and-sorting

Conversation

@MaxMichel2

Copy link
Copy Markdown
Collaborator

Summary

Implements PR 10 from the NetworkMock backlog handoff: operation tags (#116) and list sorting (#117).

Tags (#116)

  • OperationObject (OpenAPI parser model) and the public Operation model both gain tags: List<String> (default emptyList(), additive — no breaking change).
  • Read verbatim from the operation's OpenAPI tags array by OpenApiParser.parse(), the same way version/failureRate are already threaded through.
  • Purely a display/filter label, like Operation.versionno effect on request matching.
  • NetworkMockScreen gains a fourth per-tab filter chip row (tag_filter_row), multi-select, hidden entirely when the current spec has no tagged operations — following the exact same pattern as the existing method filter row.

Sorting (#117)

  • New overflow control (spec order / path A-Z / method / tag) via OperationSort + sortedByOption.
  • "Tag" is omitted from the menu entirely when the current spec has no tagged operations.
  • Sort selection is per-spec-tab, plain remember/mutableStateMapOf state in NetworkMockScreen's ContentStatenot the ViewModel, matching this screen's established filter convention (see devview-networkmock/CLAUDE.md).
  • OperationSort/sortedByOption are internal rather than private specifically so ordering can be unit-tested directly (NetworkMockScreenSortTest.kt, commonTest) without a full Compose UI test.

Design decision: sort control placement

The handoff prompt describes the sort control as an overflow DropdownMenu "in the top app bar area." NetworkMockScreen doesn't have a TopAppBar of its own, and the shared devview/DevView.kt TopAppBar (used for this module's existing "Reset to Network"/"Reload Config" actions) only supports a single-tap IconButton per action — no slot for an anchored, multi-item DropdownMenu, and it has no access to ContentState's local state anyway.

Rather than extending that shared, cross-module Action model for the sake of one screen, the sort control is a plain trailing-aligned Row local to this screen's own content (above the global mock toggle) — fully scoped to this module, matches "top app bar area" in spirit, and avoids a second nested Scaffold.topBar duplicating Material app-bar chrome/insets under the global one.

Testing

  • MockConfigRepositoryTest: new tags-parsing tests (JSON fixture + existing real-world YAML fixture, which already had an unused tags block anticipating this PR).
  • NetworkMockScreenSortTest (new, commonTest): unit tests for each OperationSort key.
  • NetworkMockScreenTest (androidDeviceTest): new tag filter-row presence/absence, single/union selection, and sort-menu tests.
  • docs/modules/networkmock-core.md gains a "Tags" section; docs/modules/networkmock-ui.md documents the tag filter row and sort control.
  • api.txt regenerated for devview-networkmock-core via metalavaGenerateSignature.

Verification run locally

  • :devview-networkmock-core:testAndroidHostTest / :devview-networkmock:testAndroidHostTest — ✅
  • :konsist:test — ✅
  • detektFull — ✅
  • :devview-networkmock:compileAndroidDeviceTest — ✅
  • :sample:androidApp:assembleDebug — ✅

Closes #116, closes #117.

@MaxMichel2
MaxMichel2 force-pushed the feat/networkmock-tags-and-sorting branch from 632c248 to 823cb8d Compare September 23, 2026 16:01
Operations can now declare OpenAPI tags - previously silently ignored (the
parser's own KDoc listed it among unmodeled fields). OperationObject/Operation
both gain tags: List<String> (empty by default, additive), threaded through
OpenApiParser.parse() the same way version/failureRate already are. Purely a
display/filter label, like version - no effect on request matching.

NetworkMockScreen gains a fourth per-tab filter chip row (tag_filter_row,
multi-select, hidden when the current spec has no tagged operations) following
the exact same pattern as the method row, and a sort control (spec order,
path, method, tag - OperationSort/sortedByOption, internal rather than
private specifically so ordering can be unit-tested directly without a full
Compose UI test). Sort state lives in ContentState's own mutableStateMapOf,
per spec tab, exactly like every other filter here - not the ViewModel.

Placement of the sort control deliberately isn't the shared DevView.kt
TopAppBar the handoff doc's prompt describes: NetworkMockScreen has no
TopAppBar of its own, and DevView.kt's per-destination action(icon) { onClick }
DSL only supports a single-tap icon (optionally with a confirm AlertDialog),
with no slot for an anchored multi-item DropdownMenu - and sort state has to
live in ContentState, which that shared bar has no access to anyway. Instead
it's a plain trailing-aligned row local to this screen's own content, above
the global mock toggle - keeps the change fully scoped to this module,
matches "top app bar area" in spirit, and avoids a second nested Scaffold
topBar duplicating Material app-bar chrome/insets under the global one.

api.txt regenerated for devview-networkmock-core (via
metalavaGenerateSignature); docs/modules/networkmock-core.md gains a "Tags"
section, docs/modules/networkmock-ui.md documents the tag filter row and
sort control.
@MaxMichel2
MaxMichel2 force-pushed the feat/networkmock-tags-and-sorting branch from 823cb8d to 045f84f Compare September 23, 2026 16:33
@MaxMichel2 MaxMichel2 added this to the 0.2.0 milestone Sep 23, 2026
@MaxMichel2 MaxMichel2 self-assigned this Sep 23, 2026
@MaxMichel2
MaxMichel2 added this pull request to stack #130 September 23, 2026 16:36
DevView's shared top app bar could only render a single-tap icon action
(optionally guarded by a confirm/cancel popup) - a control offering several
discrete choices (e.g. "Sort by: Path / Method / Tag") had nowhere to live
except inside a module's own screen content, duplicating chrome.

ModuleDestinationAction gains menuItems: PersistentList<ModuleDestinationActionMenuItem>?
(new public class ModuleDestinationActionMenuItem: label + onClick).
DestinationMetadataBuilder gains a menu(icon) { item(label) { ... } } DSL
alongside the existing action(icon) { ... }. DevView.kt's TopAppBar renders
menuItems as an anchored DropdownMenu when present; precedence when an icon
is tapped is menuItems -> popup -> action, and a menu action's own action
lambda defaults to a no-op (only the individual item callbacks fire).

NetworkMock's "Sort" toolbar action - previously a single-tap icon that
cycled spec order -> path -> method -> tag on every tap, a workaround noted
explicitly at the time as "the shared toolbar action model only supports a
single-tap icon" - now uses menu(...) to offer all four OperationSort
options directly. Picking "Tag" when the current spec has no tagged
operations is a harmless no-op (sortedByOption sorts by each operation's
absent first tag, an equal empty string for all).

OperationSort itself stays internal (sort is a pure client-side composable
concern per this module's own convention, never part of the public API) even
though NetworkMockScreen - a public composable - now needs to carry a
selected sort across the module boundary: the flow crossing NetworkMock ->
NetworkMockScreen carries OperationSort.label: String instead, mapped back
to the enum inside ContentState. A public composable can't expose an
internal type in its signature, and both ends of this label-based protocol
live in this module.

Tests: DestinationMetadataExtensionsTest covers the new menu DSL;
NetworkMockScreenTest's sort test now asserts direct selection instead of
cycling; new NetworkMockModuleTest verifies the toolbar registers
Refresh/Sort-menu/Reset in order with the correct menu labels.

api.txt regenerated for devview and devview-networkmock (metalavaGenerateSignature).
devview/CLAUDE.md documents the menu DSL; devview-networkmock/CLAUDE.md gains
a "Sort" toolbar dropdown section (and a missing tag filter row mention);
docs/modules/networkmock-ui.md and CHANGELOG.md updated to match.
The nav-bar inset (bottomPadding) was applied to the whole bottom bar Surface, pushing every filter chip row down along with the search field and expand button. Now it's applied only to the search field and expand button themselves, matching AnalyticsScreen's existing layout.

Also expands the sample app's jsonplaceholder.json spec from 4 to 24 tagged operations (Users/Posts/Comments/Albums/Photos/Todos) to manually validate the fix with a realistically long, scrollable endpoint list.

Verified: 69/69 devview-networkmock device tests pass on a physical device.
@MaxMichel2
MaxMichel2 force-pushed the feat/networkmock-tags-and-sorting branch from 02be00b to 25538c6 Compare September 24, 2026 06:18

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant