feat: serve response headers and content type declared in the spec - #127
Open
MaxMichel2 wants to merge 1 commit into
Open
MaxMichel2 wants to merge 1 commit into
MaxMichel2 wants to merge 1 commit into
Conversation
Mocked responses always carried a single hardcoded Content-Type: application/json header, with no way to declare additional headers per response - and even the spec's own declared media type (the key under responses.<code>.content) was discarded during parsing. - OpenApiDocument: HeaderObject DTO, ResponseObject.headers. - OpenApiParser.resolveResponseIndex now threads the media-type key and resolves declared headers (a header's literal example value, same pattern as query parameter matching) into a new ResolvedResponse record, replacing the bare file-path string the response index used to carry. Header $refs resolve against components.headers. - MockResponse gains contentType (default "application/json") and headers (default empty) properties, threaded through MockConfigRepository and into the Ktor plugin's synthetic HttpResponseData via a HeadersBuilder - declared headers merge over the Content-Type default, and an explicit Content-Type header in the spec wins over the media-type-derived one. New public API on MockResponse is additive/defaulted - no existing call site needed updating. api.txt regenerated. Closes #87. Also closes gap 7 of #91 (no assertion on response headers/content-type in NetworkMockPluginTest.kt). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Sep 22, 2026
MaxMichel2
added this pull request to stack #130
September 22, 2026 12:07
This was referenced Sep 23, 2026
MaxMichel2
added a commit
that referenced
this pull request
Sep 23, 2026
Re-scoped issue #91's gap list against current code before writing anything (the issue predates the OpenAPI migration and named files/classes that no longer exist) and found four of its seven gaps already closed by prior work: - Delay precedence: covered except the "neither declares one -> null" case - extended with one more test (existing test already covers operation-level override and spec-default fallback). - Ambiguous host-match precedence: already fully covered by MockConfigRepositoryTest's two "hosts collide" tests. No action. - Preview/diff bottom sheet: already fully covered by MockResponsePreviewPageTest.kt (the page) and DiffLineUtilsTest.kt (the diff logic it drives). No action. - Response Content-Type/header assertions: already closed by #127 (returnsMockResponse_withDefaultContentTypeHeader / _withDeclaredHeadersAndContentType). No action. Three gaps remained genuinely open: - Real sample spec parsing: no test previously loaded the actual shipped sample specs (sample/network's sample-api.json, jsonplaceholder.json) through the real MockConfigRepository - every existing test uses hand-built inline fixtures, so the shipped sample could silently drift out of sync with what the parser accepts. New RealSampleSpecTest (androidHostTest, since java.io.File isn't available on Kotlin/Native and this is a plain JVM sanity check) reads them directly off disk via a Gradle-configured devview.sampleNetworkResourcesDir system property, computed once at configuration time from rootProject.file(...) so the test doesn't depend on the JVM working directory - deliberately not a compile-time dependency on the sample module, which would invert this module's place in the dependency graph. - Query-parameter matching end-to-end through the Ktor plugin: RequestMatcherTest already covered matchesQueryParams in isolation, but NetworkMockPluginTest had no end-to-end coverage through the actual interception path. KtorPluginTestData's shared spec gains a listUsers operation (?type=user, mirroring the real sample spec's own listUsers) and NetworkMockPluginTest gains a "Query parameter matching" region: matches on the declared value, falls through to network on a different value or a missing param. - Sticky-header status-family grouping: OperationPickerPage's response list already groups by StatusCodeFamily with a sticky header per group, but nothing asserted the header text itself or that responses actually land in distinct groups - NetworkMockOperationSheetTest's existing 200/404 fixture already spans two families, so one added test closes this by asserting both family headers render. CHANGELOG.md documents this as a coverage-closing entry rather than a user-facing change (nothing here alters library behavior).
MaxMichel2
added a commit
that referenced
this pull request
Sep 23, 2026
Re-scoped issue #91's gap list against current code before writing anything (the issue predates the OpenAPI migration and named files/classes that no longer exist) and found four of its seven gaps already closed by prior work: - Delay precedence: covered except the "neither declares one -> null" case - extended with one more test (existing test already covers operation-level override and spec-default fallback). - Ambiguous host-match precedence: already fully covered by MockConfigRepositoryTest's two "hosts collide" tests. No action. - Preview/diff bottom sheet: already fully covered by MockResponsePreviewPageTest.kt (the page) and DiffLineUtilsTest.kt (the diff logic it drives). No action. - Response Content-Type/header assertions: already closed by #127 (returnsMockResponse_withDefaultContentTypeHeader / _withDeclaredHeadersAndContentType). No action. Three gaps remained genuinely open: - Real sample spec parsing: no test previously loaded the actual shipped sample specs (sample/network's sample-api.json, jsonplaceholder.json) through the real MockConfigRepository - every existing test uses hand-built inline fixtures, so the shipped sample could silently drift out of sync with what the parser accepts. New RealSampleSpecTest (androidHostTest, since java.io.File isn't available on Kotlin/Native and this is a plain JVM sanity check) reads them directly off disk via a Gradle-configured devview.sampleNetworkResourcesDir system property, computed once at configuration time from rootProject.file(...) so the test doesn't depend on the JVM working directory - deliberately not a compile-time dependency on the sample module, which would invert this module's place in the dependency graph. - Query-parameter matching end-to-end through the Ktor plugin: RequestMatcherTest already covered matchesQueryParams in isolation, but NetworkMockPluginTest had no end-to-end coverage through the actual interception path. KtorPluginTestData's shared spec gains a listUsers operation (?type=user, mirroring the real sample spec's own listUsers) and NetworkMockPluginTest gains a "Query parameter matching" region: matches on the declared value, falls through to network on a different value or a missing param. - Sticky-header status-family grouping: OperationPickerPage's response list already groups by StatusCodeFamily with a sticky header per group, but nothing asserted the header text itself or that responses actually land in distinct groups - NetworkMockOperationSheetTest's existing 200/404 fixture already spans two families, so one added test closes this by asserting both family headers render. CHANGELOG.md documents this as a coverage-closing entry rather than a user-facing change (nothing here alters library behavior).
MaxMichel2
added a commit
that referenced
this pull request
Sep 24, 2026
Re-scoped issue #91's gap list against current code before writing anything (the issue predates the OpenAPI migration and named files/classes that no longer exist) and found four of its seven gaps already closed by prior work: - Delay precedence: covered except the "neither declares one -> null" case - extended with one more test (existing test already covers operation-level override and spec-default fallback). - Ambiguous host-match precedence: already fully covered by MockConfigRepositoryTest's two "hosts collide" tests. No action. - Preview/diff bottom sheet: already fully covered by MockResponsePreviewPageTest.kt (the page) and DiffLineUtilsTest.kt (the diff logic it drives). No action. - Response Content-Type/header assertions: already closed by #127 (returnsMockResponse_withDefaultContentTypeHeader / _withDeclaredHeadersAndContentType). No action. Three gaps remained genuinely open: - Real sample spec parsing: no test previously loaded the actual shipped sample specs (sample/network's sample-api.json, jsonplaceholder.json) through the real MockConfigRepository - every existing test uses hand-built inline fixtures, so the shipped sample could silently drift out of sync with what the parser accepts. New RealSampleSpecTest (androidHostTest, since java.io.File isn't available on Kotlin/Native and this is a plain JVM sanity check) reads them directly off disk via a Gradle-configured devview.sampleNetworkResourcesDir system property, computed once at configuration time from rootProject.file(...) so the test doesn't depend on the JVM working directory - deliberately not a compile-time dependency on the sample module, which would invert this module's place in the dependency graph. - Query-parameter matching end-to-end through the Ktor plugin: RequestMatcherTest already covered matchesQueryParams in isolation, but NetworkMockPluginTest had no end-to-end coverage through the actual interception path. KtorPluginTestData's shared spec gains a listUsers operation (?type=user, mirroring the real sample spec's own listUsers) and NetworkMockPluginTest gains a "Query parameter matching" region: matches on the declared value, falls through to network on a different value or a missing param. - Sticky-header status-family grouping: OperationPickerPage's response list already groups by StatusCodeFamily with a sticky header per group, but nothing asserted the header text itself or that responses actually land in distinct groups - NetworkMockOperationSheetTest's existing 200/404 fixture already spans two families, so one added test closes this by asserting both family headers render. CHANGELOG.md documents this as a coverage-closing entry rather than a user-facing change (nothing here alters library behavior).
MaxMichel2
added a commit
that referenced
this pull request
Sep 24, 2026
Re-scoped issue #91's gap list against current code before writing anything (the issue predates the OpenAPI migration and named files/classes that no longer exist) and found four of its seven gaps already closed by prior work: - Delay precedence: covered except the "neither declares one -> null" case - extended with one more test (existing test already covers operation-level override and spec-default fallback). - Ambiguous host-match precedence: already fully covered by MockConfigRepositoryTest's two "hosts collide" tests. No action. - Preview/diff bottom sheet: already fully covered by MockResponsePreviewPageTest.kt (the page) and DiffLineUtilsTest.kt (the diff logic it drives). No action. - Response Content-Type/header assertions: already closed by #127 (returnsMockResponse_withDefaultContentTypeHeader / _withDeclaredHeadersAndContentType). No action. Three gaps remained genuinely open: - Real sample spec parsing: no test previously loaded the actual shipped sample specs (sample/network's sample-api.json, jsonplaceholder.json) through the real MockConfigRepository - every existing test uses hand-built inline fixtures, so the shipped sample could silently drift out of sync with what the parser accepts. New RealSampleSpecTest (androidHostTest, since java.io.File isn't available on Kotlin/Native and this is a plain JVM sanity check) reads them directly off disk via a Gradle-configured devview.sampleNetworkResourcesDir system property, computed once at configuration time from rootProject.file(...) so the test doesn't depend on the JVM working directory - deliberately not a compile-time dependency on the sample module, which would invert this module's place in the dependency graph. - Query-parameter matching end-to-end through the Ktor plugin: RequestMatcherTest already covered matchesQueryParams in isolation, but NetworkMockPluginTest had no end-to-end coverage through the actual interception path. KtorPluginTestData's shared spec gains a listUsers operation (?type=user, mirroring the real sample spec's own listUsers) and NetworkMockPluginTest gains a "Query parameter matching" region: matches on the declared value, falls through to network on a different value or a missing param. - Sticky-header status-family grouping: OperationPickerPage's response list already groups by StatusCodeFamily with a sticky header per group, but nothing asserted the header text itself or that responses actually land in distinct groups - NetworkMockOperationSheetTest's existing 200/404 fixture already spans two families, so one added test closes this by asserting both family headers render. CHANGELOG.md documents this as a coverage-closing entry rather than a user-facing change (nothing here alters library behavior).
This branch has not been deployed
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
Closes #87. Also closes gap 7 of #91 (no assertion on response headers/content-type in
NetworkMockPluginTest.kt).Stacked on #124 (PR chain: #123 → #124 → this) — merge in order.
Mocked responses always carried a single hardcoded
Content-Type: application/jsonheader, with no way to declare additional headers per response. Worse, the parser already discarded the spec's own declared media type (the key underresponses.<code>.content) while walking down to the example — so even a spec explicitly describingtext/plainor a vendor JSON type was silently forced toapplication/json.What changed
OpenApiDocument: newHeaderObjectDTO,ResponseObject.headers,ComponentsObject.headers(for$reftargets).OpenApiParser:resolveResponseIndexnow threads the media-type key (previously discarded) and resolves declared headers — a header's literalexamplevalue, the same pattern query-parameter matching already uses — into a newResolvedResponserecord (path,contentType,headers), replacing the bare file-path string the response index used to carry. Header$refs resolve againstcomponents.headers, reusing the existing one-level-deep$refresolution.MockResponse: gainscontentType(default"application/json") andheaders(default empty) properties, threaded throughMockConfigRepository.loadResponseFromPath.NetworkMockPlugin:createMockHttpClientCallnow builds the response'sHeadersvia aHeadersBuilder— declared headers merge over theContent-Typedefault rather than replacing it, and an explicitContent-Typeentry under the spec's ownheaderswins over the media-type-derived default.Public API
Additive/defaulted — no existing call site needed updating.
devview-networkmock-core/api/api.txtregenerated viametalavaGenerateSignature.Tests
MockConfigRepositoryTest: content-type/headers threading, a$ref'd header resolving viacomponents.headers, and the existingloadMockResponsetest extended to assert theapplication/jsondefault.NetworkMockPluginTest: two new tests —Content-Typepresent by default (closes test: cover the gaps left by the audit #91 gap 7), and declared headers + a non-default content type reaching the response the app actually receives.Docs:
networkmock-core.md(new "Response headers and content type" section),networkmock-ktor.md(interception summary),devview-networkmock-ktor/CLAUDE.md(corrected the stale "empty headers" claim).Verification
All green, including a full repo-wide
testAndroidHostTestrun to confirm no fallout outside the networkmock modules.🤖 Generated with Claude Code