Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 11 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@
</a>
</p>

<h1 align="center">react-native-coverage</h1>

<p align="center">
<strong>Native code coverage for React Native — iOS <em>and</em> Android — without touching the native stuff.</strong>
</p>

<p align="center">
A TurboModule flushes real device coverage. A CLI pulls it, turns it into LCOV / Jacoco,<br/>
and fails your CI when the numbers are empty. That's it.
</p>
<h1 align="center">Code coverage for React Native — Typescript, iOS, and Android — without touching the native stuff.</h1>

<p align="center">
<a href="https://app.codecov.io/gh/invertase/react-native-coverage"><img src="https://codecov.io/gh/invertase/react-native-coverage/branch/main/graph/badge.svg" alt="Codecov" /></a>
Expand All @@ -23,7 +14,11 @@
</p>

<p align="center">
<strong>Integrate with your favorite tools</strong> — for visibility, or as a workflow quality gate during development.
Install it into a dedicated test / e2e harness app (<a href="https://docs.page/invertase/react-native-coverage/pattern-c">Pattern&nbsp;C</a>) — never your shipping app.
</p>

<p align="center">
A TurboModule flushes real device coverage; the CLI pulls it, <strong>merges</strong> every framework's <code>.profraw</code> and the app binary into clean LCOV&nbsp;/&nbsp;Jacoco, and remaps your instrumented JS line-for-line back to TypeScript. Use that as a signal in your development loop or CI to gate development iterations or CI pass/fail.
</p>

<p align="center">
Expand All @@ -49,15 +44,11 @@ JS ran. In an agentic world where a model can rewrite your `.mm` file and swear
**that missing evidence is a real problem.** Coverage is the backpressure. It's how you — or
your agent — prove the native path executed, not just the mock.

`react-native-coverage` makes that evidence a one-liner:

```
Coverage.flush() → rn-coverage pull → LCOV / Jacoco → rn-coverage assert (fail CI if empty)
```
`react-native-coverage` makes that evidence a one-liner: flush from the TurboModule, `rn-coverage pull`
to merge the scattered native counters and remap your JS back to TypeScript, then `rn-coverage assert`
to turn "did the native path actually run?" into a pass/fail signal for your dev loop or CI.

No Podfile regex. No profraw archaeology. No Gradle spelunking. New Architecture only,
[Pattern C](https://docs.page/invertase/react-native-coverage/pattern-c) (dedicated test
apps only — never your shipping app).
No Podfile regex. No profraw archaeology. No Gradle spelunking.

---

Expand All @@ -73,13 +64,7 @@ This repository **proves its own thesis on Codecov, live on `main`** — includi
| [`unit-js`](https://app.codecov.io/gh/invertase/react-native-coverage) | Jest unit (JS/TS) | **52.6%** |

Those numbers come from an actual iOS Simulator and Android emulator running the harness apps
under Appium — not from a mock. Browse them yourself:

**The iOS native directory, with per-file line coverage** — [`ios/` on Codecov →](https://app.codecov.io/gh/invertase/react-native-coverage/tree/main/ios)

<p align="center">
<img src="./docs/assets/codecov/ios-tree.png" alt="Codecov file explorer showing ios/ native directory with line coverage for Coverage.mm, CoverageProfile.mm and CoverageConfig.h" width="900" />
</p>
under Appium — not from a mock. Browse the [`ios/` native directory on Codecov →](https://app.codecov.io/gh/invertase/react-native-coverage/tree/main/ios) yourself.

**The TurboModule itself, line by line** — [`ios/Coverage.mm` on Codecov →](https://app.codecov.io/gh/invertase/react-native-coverage/blob/main/ios/Coverage.mm)
Real Objective-C++ (`flush()`, `dumpJsCoverage`, `getTurboModule`), green where a device
Expand Down
Binary file modified docs/assets/codecov/ios-tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 7 additions & 16 deletions docs/index.mdx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
---
title: react-native-coverage
description: Native code coverage for React Native - iOS and Android - without touching the native stuff.
title: Code coverage for React Native - Typescript, iOS, and Android - without touching the native stuff.
description: Flush real device coverage from a TurboModule, merge it into LCOV / Jacoco, remap TypeScript line-for-line, and gate your dev loop or CI.
---

**Native code coverage for React Native — iOS _and_ Android — without touching the native stuff.**
Install it into a dedicated test / e2e harness app ([Pattern C](/pattern-c)) — never your shipping app.

A TurboModule flushes real device coverage. A CLI pulls it, turns it into LCOV / Jacoco, and
fails your CI when the numbers are empty. That's the whole product.

```
Coverage.flush() → rn-coverage pull → LCOV / Jacoco → rn-coverage assert (fail CI if empty)
```

<Info>
New Architecture / TurboModule only. Install into a **dedicated test / e2e harness app**
([Pattern C](/pattern-c)) — never your shipping app.
</Info>

**Integrate with your favorite tools** — for visibility, or as a workflow quality gate during development.
A TurboModule flushes real device coverage; the CLI pulls it, **merges** every framework's `.profraw` and the
app binary into clean LCOV / Jacoco, and remaps your instrumented JS line-for-line back to TypeScript — smoothing
the rough edges of modern TypeScript development by handling the line-accurate source mapping for you. Use that as
a signal in your development loop or CI to gate development iterations or CI pass/fail.

[![Codecov dashboard for react-native-coverage — overall coverage, 3-month trend, sunburst graph, and the native code tree](/assets/codecov/dashboard.png)](https://app.codecov.io/gh/invertase/react-native-coverage)

Expand Down
8 changes: 3 additions & 5 deletions docs/why.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ tested. Coverage is the backpressure that keeps that honest. It is the differenc
device." Without native coverage, an agent — or a human — can hand-wave past the hardest,
most platform-specific code in the app.

`react-native-coverage` turns that missing evidence into a one-liner:

```
Coverage.flush() → rn-coverage pull → LCOV / Jacoco → rn-coverage assert (fail CI if empty)
```
`react-native-coverage` turns that missing evidence into a one-liner: flush from the TurboModule,
`rn-coverage pull` to merge the scattered native counters and remap your JS back to TypeScript, then
`rn-coverage assert` to turn "did the native path actually run?" into a pass/fail signal for your dev loop or CI.

No Podfile regex. No profraw archaeology. No Gradle spelunking.

Expand Down
Loading