Skip to content

test: increase unit test coverage including Speak V2 Flux TTS#514

Open
mgama-deepgram wants to merge 7 commits into
mainfrom
increase_unit_test_coverage
Open

test: increase unit test coverage including Speak V2 Flux TTS#514
mgama-deepgram wants to merge 7 commits into
mainfrom
increase_unit_test_coverage

Conversation

@mgama-deepgram

@mgama-deepgram mgama-deepgram commented Jun 30, 2026

Copy link
Copy Markdown

Proposed changes

  • Adding code coverage processes on the CI.yml workflow on the test job
  • The test job in the CI.yml workflow will now post the calculated code coverage as a PR comment
  • Increases code coverage (aided by analysis via Claude). Increasing from line rate at 36% to 98%, and from branch rate at 24% to 95%
  • Replaces original PR to only calculate test coverage docs(tests): adding code coverage processes on CI.yml workflow #511

Increase unit test coverage + coverage reporting in CI

Summary

Adds a comprehensive hand-written unit test suite across the SDK's hand-maintainable surface (core utilities, transport/websocket layer, custom client, generated REST/WS clients, and Speak V2), wires V8 code coverage into CI with an automatic PR comment, and repairs a lockfile broken by an earlier merge. All new tests are frozen in .fernignore so they survive the next Fern regeneration.

18 new test files, 1167 unit tests passing.

What changed

CI (.github/workflows/ci.yml)

  • Runs on pull_request in addition to push.
  • Test step now runs make test-coverage (unit + wire under V8 coverage).
  • Generates a coverage summary (CodeCoverageSummary), posts/updates a sticky PR comment, and writes it to the job summary. Grants the test job pull-requests: write.

Tooling

  • Makefile — new test-coverage target: runs unit + wire in a single vitest invocation so coverage merges into one cobertura + text report (CI reads coverage/cobertura-coverage.xml); the wire-import fixup is reverted even on failure.
  • vitest.config.mts — normalized project root/include paths and added a coverage block (v8, src/**/*.ts, ./coverage).
  • .fernignore — froze all new hand-written test files (and the tests/unit/core dir) so a regen won't delete them.

New test coverage (new files unless noted)

  • Core: core/polyfills, core/reconnecting-websocket, core/runtime-detection, core/utils, core-branches, misc-branches, fetcher-branches.
  • Transport / websockets: websocket-native, websocket-sockets (generated Socket classes), generated-ws-clients (generated connect() query serialization).
  • Custom client: custom-client-internals, custom-client-browser, custom-client-fallback.
  • REST / misc: rest-clients, barrels, auth/HeaderAuthProvider, file/multipart.

Lockfile repair (package.json, pnpm-lock.yaml)

  • Fixed a pnpm-lock.yaml broken by a bad merge (dependency graph referenced cosmiconfig@9.0.2 while only 9.0.1 was defined → ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY in CI).
  • Rebased the lockfile on main's clean version and pinned @vitest/coverage-v8 to 4.1.9 to match vitest@4.1.9 (required by strict-peer-dependencies). pnpm install --frozen-lockfile now passes.

🎙️ Speak V2 (Flux TTS) — coverage changes

All Speak V2 changes in this PR, grouped for review:

New: tests/unit/speak-v2-coverage.test.ts (mirrors the Python SDK's test_speak_v2_coverage.py)
Raises coverage of src/api/resources/speak/resources/v2/** from 58% → 100% statements / 32% → 98% branches:

File Before After
client/Client.ts 28.6% 100%
client/Socket.ts 36% 100%
resources/audio/client/Client.ts 64.3% 100%

Covers the gaps left by the existing split tests:

  • Client.ts connect() (absent from generated-ws-clients.test.ts) — query-param serialization (string vs toJson branches), absent-param omission, queryParams/headers/options merge, and the audio lazy getter. Uses an aborted signal so no real socket opens.
  • Socket.ts (absent from the describe.each in websocket-sockets.test.ts) — event forwarding, readyState, send guards + open path, connect()/close() teardown, all three waitForOpen() cases, sendBinary, and the Socket is not connected guard.
  • audio/client/Client.ts (speak-v2-batch.test.ts only drove the 2xx path) — the 400 → BadRequestError, non-400 → DeepgramError, and transport-failure → handleNonStatusCodeError branches, plus an all-optional-params success case.

The one uncovered branch (audio/Client.ts:79, the ?? Production env fallback) is only reachable with no configured environment — it would hit the real production host, so it's intentionally left.

Modified: tests/unit/regen-constraints.test.ts
Added two tests pinning the complete member set of SpeakV2Encoding and SpeakV2SampleRate. The pre-existing test only asserted one member per enum — a regen dropping/renaming a value (e.g. removing the 44100 sample rate) would have kept coverage at 100% but slipped through. Both also assert the open-string union still holds. (The other SpeakV2* types under src/api/types are pure type aliases with no runtime code, so they're already effectively fully covered.)

.fernignore — froze tests/unit/speak-v2-coverage.test.ts (regen-constraints.test.ts was already frozen).

Types of changes

What types of changes does your code introduce to the community JavaScript SDK?
Put an x in the boxes that apply

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update or tests (if none of the other choices apply)

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • I have read the CONTRIBUTING doc
  • I have lint'ed all of my code using repo standards
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Further comments

@mgama-deepgram mgama-deepgram changed the title Increase unit test coverage test: increase unit test coverage Jun 30, 2026
@mgama-deepgram
mgama-deepgram marked this pull request as ready for review June 30, 2026 22:58
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage

Package Line Rate Branch Rate Health
src 97% 84%
src.api 100% 100%
src.api.errors 100% 50%
src.api.resources 100% 100%
src.api.resources.agent 100% 100%
src.api.resources.agent.client 50% 100%
src.api.resources.agent.resources 100% 100%
src.api.resources.agent.resources.v1 100% 100%
src.api.resources.agent.resources.v1.client 99% 90%
src.api.resources.agent.resources.v1.resources 100% 100%
src.api.resources.agent.resources.v1.resources.settings 100% 100%
src.api.resources.agent.resources.v1.resources.settings.client 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources.think 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources.think.client 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources.think.resources 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources.think.resources.models 100% 100%
src.api.resources.agent.resources.v1.resources.settings.resources.think.resources.models.client 100% 100%
src.api.resources.agent.resources.v1.types 100% 100%
src.api.resources.auth 100% 100%
src.api.resources.auth.client 100% 100%
src.api.resources.auth.resources 100% 100%
src.api.resources.auth.resources.v1 100% 100%
src.api.resources.auth.resources.v1.client 100% 100%
src.api.resources.auth.resources.v1.resources 100% 100%
src.api.resources.auth.resources.v1.resources.tokens 100% 100%
src.api.resources.auth.resources.v1.resources.tokens.client 100% 100%
src.api.resources.auth.resources.v1.resources.tokens.client.requests 100% 100%
src.api.resources.listen 100% 100%
src.api.resources.listen.client 33% 100%
src.api.resources.listen.resources 100% 100%
src.api.resources.listen.resources.v1 100% 100%
src.api.resources.listen.resources.v1.client 98% 98%
src.api.resources.listen.resources.v1.resources 100% 100%
src.api.resources.listen.resources.v1.resources.media 100% 100%
src.api.resources.listen.resources.v1.resources.media.client 100% 100%
src.api.resources.listen.resources.v1.resources.media.client.requests 100% 100%
src.api.resources.listen.resources.v1.resources.media.types 100% 100%
src.api.resources.listen.resources.v1.types 100% 100%
src.api.resources.listen.resources.v2 100% 100%
src.api.resources.listen.resources.v2.client 98% 92%
src.api.resources.listen.resources.v2.types 100% 100%
src.api.resources.manage 100% 100%
src.api.resources.manage.client 100% 100%
src.api.resources.manage.resources 100% 100%
src.api.resources.manage.resources.v1 100% 100%
src.api.resources.manage.resources.v1.client 100% 100%
src.api.resources.manage.resources.v1.resources 100% 100%
src.api.resources.manage.resources.v1.resources.models 100% 100%
src.api.resources.manage.resources.v1.resources.models.client 100% 100%
src.api.resources.manage.resources.v1.resources.models.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects 100% 100%
src.api.resources.manage.resources.v1.resources.projects.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.balances 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.balances.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.breakdown 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.breakdown.client 100% 96%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.breakdown.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.breakdown.types 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.fields 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.fields.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.fields.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.purchases 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.purchases.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.billing.resources.purchases.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.keys 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.keys.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.keys.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.keys.types 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.invites 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.invites.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.invites.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.scopes 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.scopes.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.members.resources.scopes.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.models 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.models.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.models.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.requests.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.requests.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.requests.types 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.breakdown 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.breakdown.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.breakdown.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.breakdown.types 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.fields 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.fields.client 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.resources.fields.client.requests 100% 100%
src.api.resources.manage.resources.v1.resources.projects.resources.usage.types 100% 100%
src.api.resources.read 100% 100%
src.api.resources.read.client 100% 100%
src.api.resources.read.resources 100% 100%
src.api.resources.read.resources.v1 100% 100%
src.api.resources.read.resources.v1.client 100% 100%
src.api.resources.read.resources.v1.resources 100% 100%
src.api.resources.read.resources.v1.resources.text 100% 100%
src.api.resources.read.resources.v1.resources.text.client 100% 100%
src.api.resources.read.resources.v1.resources.text.client.requests 100% 100%
src.api.resources.read.resources.v1.resources.text.types 100% 100%
src.api.resources.selfHosted 100% 100%
src.api.resources.selfHosted.client 100% 100%
src.api.resources.selfHosted.resources 100% 100%
src.api.resources.selfHosted.resources.v1 100% 100%
src.api.resources.selfHosted.resources.v1.client 100% 100%
src.api.resources.selfHosted.resources.v1.resources 100% 100%
src.api.resources.selfHosted.resources.v1.resources.distributionCredentials 100% 100%
src.api.resources.selfHosted.resources.v1.resources.distributionCredentials.client 100% 99%
src.api.resources.selfHosted.resources.v1.resources.distributionCredentials.client.requests 100% 100%
src.api.resources.selfHosted.resources.v1.resources.distributionCredentials.types 100% 100%
src.api.resources.speak 100% 100%
src.api.resources.speak.client 33% 100%
src.api.resources.speak.resources 100% 100%
src.api.resources.speak.resources.v1 100% 100%
src.api.resources.speak.resources.v1.client 97% 93%
src.api.resources.speak.resources.v1.resources 100% 100%
src.api.resources.speak.resources.v1.resources.audio 100% 100%
src.api.resources.speak.resources.v1.resources.audio.client 100% 100%
src.api.resources.speak.resources.v1.resources.audio.client.requests 100% 100%
src.api.resources.speak.resources.v1.resources.audio.types 100% 100%
src.api.resources.speak.resources.v1.types 100% 100%
src.api.resources.speak.resources.v2 100% 100%
src.api.resources.speak.resources.v2.client 100% 100%
src.api.resources.speak.resources.v2.resources 100% 100%
src.api.resources.speak.resources.v2.resources.audio 100% 100%
src.api.resources.speak.resources.v2.resources.audio.client 100% 96%
src.api.resources.speak.resources.v2.resources.audio.client.requests 100% 100%
src.api.resources.speak.resources.v2.resources.audio.types 100% 100%
src.api.resources.speak.resources.v2.types 100% 100%
src.api.resources.voiceAgent 100% 100%
src.api.resources.voiceAgent.client 100% 100%
src.api.resources.voiceAgent.resources 100% 100%
src.api.resources.voiceAgent.resources.configurations 100% 100%
src.api.resources.voiceAgent.resources.configurations.client 100% 100%
src.api.resources.voiceAgent.resources.configurations.client.requests 100% 100%
src.api.resources.voiceAgent.resources.variables 100% 100%
src.api.resources.voiceAgent.resources.variables.client 100% 100%
src.api.resources.voiceAgent.resources.variables.client.requests 100% 100%
src.api.types 100% 100%
src.auth 100% 89%
src.core 98% 90%
src.core.auth 88% 91%
src.core.fetcher 97% 90%
src.core.file 95% 95%
src.core.logging 100% 94%
src.core.runtime 96% 97%
src.core.url 97% 98%
src.core.websocket 94% 88%
src.errors 100% 89%
Summary 98% (2904 / 2967) 95% (2202 / 2314)

@mgama-deepgram mgama-deepgram changed the title test: increase unit test coverage test: increase unit test coverage including Speak V2 Flux TTS Jul 23, 2026
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