From 41e9cb2429a7c80fa6942f1cb8d63a844f5428a5 Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Thu, 30 May 2024 09:39:09 +0900
Subject: [PATCH 1/8] Output coverage per each test

---
 .vitest.config/jsx-runtime-default.ts      | 3 +++
 .vitest.config/jsx-runtime-dom.ts          | 3 +++
 runtime_tests/bun/vitest.config.ts         | 5 +++++
 runtime_tests/fastly/vitest.config.ts      | 5 +++++
 runtime_tests/lambda-edge/vitest.config.ts | 5 +++++
 runtime_tests/lambda/vitest.config.ts      | 5 +++++
 runtime_tests/node/vitest.config.ts        | 5 +++++
 runtime_tests/wrangler/vitest.config.ts    | 5 +++++
 vitest.config.ts                           | 4 +++-
 9 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/.vitest.config/jsx-runtime-default.ts b/.vitest.config/jsx-runtime-default.ts
index 9885a19ba..a325bc047 100644
--- a/.vitest.config/jsx-runtime-default.ts
+++ b/.vitest.config/jsx-runtime-default.ts
@@ -8,5 +8,8 @@ if (config.test) {
     '**/src/jsx/dom/**/(*.)+(spec|test).+(ts|tsx|js)',
     'src/jsx/hooks/dom.test.tsx',
   ]
+  if (config.test.coverage) {
+    config.test.coverage.reportsDirectory = './coverage/raw/jsx-runtime'
+  }
 }
 export default config
diff --git a/.vitest.config/jsx-runtime-dom.ts b/.vitest.config/jsx-runtime-dom.ts
index 11adf6ccf..c9a4a3a71 100644
--- a/.vitest.config/jsx-runtime-dom.ts
+++ b/.vitest.config/jsx-runtime-dom.ts
@@ -8,5 +8,8 @@ if (config.test) {
     '**/src/jsx/dom/**/(*.)+(spec|test).+(ts|tsx|js)',
     'src/jsx/hooks/dom.test.tsx',
   ]
+  if (config.test.coverage) {
+    config.test.coverage.reportsDirectory = './coverage/raw/jsx-dom'
+  }
 }
 export default config
diff --git a/runtime_tests/bun/vitest.config.ts b/runtime_tests/bun/vitest.config.ts
index 5d244e3f1..6b1cae417 100644
--- a/runtime_tests/bun/vitest.config.ts
+++ b/runtime_tests/bun/vitest.config.ts
@@ -1,9 +1,14 @@
 /// <reference types="vitest" />
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   test: {
     globals: true,
     include: ['**/runtime_tests/bun/**/*.+(ts|tsx|js)'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-bun',
+    },
   },
 })
diff --git a/runtime_tests/fastly/vitest.config.ts b/runtime_tests/fastly/vitest.config.ts
index 89baa3577..c0480b139 100644
--- a/runtime_tests/fastly/vitest.config.ts
+++ b/runtime_tests/fastly/vitest.config.ts
@@ -1,6 +1,7 @@
 /// <reference types="vitest" />
 import fastlyCompute from 'vite-plugin-fastly-js-compute'
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   plugins: [fastlyCompute()],
@@ -8,5 +9,9 @@ export default defineConfig({
     globals: true,
     include: ['**/runtime_tests/fastly/**/(*.)+(test).+(ts|tsx)'],
     exclude: ['**/runtime_tests/fastly/vitest.config.ts'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-fastly',
+    },
   },
 })
diff --git a/runtime_tests/lambda-edge/vitest.config.ts b/runtime_tests/lambda-edge/vitest.config.ts
index 568ecc05c..105ac9505 100644
--- a/runtime_tests/lambda-edge/vitest.config.ts
+++ b/runtime_tests/lambda-edge/vitest.config.ts
@@ -1,5 +1,6 @@
 /// <reference types="vitest" />
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   test: {
@@ -9,5 +10,9 @@ export default defineConfig({
     globals: true,
     include: ['**/runtime_tests/lambda-edge/**/*.+(ts|tsx|js)'],
     exclude: ['**/runtime_tests/lambda-edge/vitest.config.ts'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-lambda-edge',
+    },
   },
 })
diff --git a/runtime_tests/lambda/vitest.config.ts b/runtime_tests/lambda/vitest.config.ts
index 0fd446dc6..f030cf410 100644
--- a/runtime_tests/lambda/vitest.config.ts
+++ b/runtime_tests/lambda/vitest.config.ts
@@ -1,5 +1,6 @@
 /// <reference types="vitest" />
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   test: {
@@ -9,5 +10,9 @@ export default defineConfig({
     globals: true,
     include: ['**/runtime_tests/lambda/**/*.+(ts|tsx|js)'],
     exclude: ['**/runtime_tests/lambda/vitest.config.ts', '**/runtime_tests/lambda/mock.ts'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-lambda',
+    },
   },
 })
diff --git a/runtime_tests/node/vitest.config.ts b/runtime_tests/node/vitest.config.ts
index a2c74bbbe..5387c11fd 100644
--- a/runtime_tests/node/vitest.config.ts
+++ b/runtime_tests/node/vitest.config.ts
@@ -1,5 +1,6 @@
 /// <reference types="vitest" />
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   test: {
@@ -9,5 +10,9 @@ export default defineConfig({
     globals: true,
     include: ['**/runtime_tests/node/**/*.+(ts|tsx|js)'],
     exclude: ['**/runtime_tests/node/vitest.config.ts'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-node',
+    },
   },
 })
diff --git a/runtime_tests/wrangler/vitest.config.ts b/runtime_tests/wrangler/vitest.config.ts
index 4b8af9b11..7eb5c620a 100644
--- a/runtime_tests/wrangler/vitest.config.ts
+++ b/runtime_tests/wrangler/vitest.config.ts
@@ -1,10 +1,15 @@
 /// <reference types="vitest" />
 import { defineConfig } from 'vitest/config'
+import config from '../../vitest.config'
 
 export default defineConfig({
   test: {
     globals: true,
     include: ['**/runtime_tests/wrangler/**/(*.)+(test).+(ts|tsx)'],
     exclude: ['**/runtime_tests/wrangler/vitest.config.ts'],
+    coverage: {
+      ...config.test?.coverage,
+      reportsDirectory: './coverage/raw/runtime-wrangler',
+    },
   },
 })
diff --git a/vitest.config.ts b/vitest.config.ts
index 90470c8b3..4065d762b 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -12,8 +12,10 @@ export default defineConfig({
     exclude: [...configDefaults.exclude, '**/sandbox/**', '**/*.case.test.+(ts|tsx|js)'],
     setupFiles: ['./src/test-utils/setup-vitest.ts'],
     coverage: {
+      enabled: true,
       provider: 'v8',
-      reporter: ['text'],
+      reportsDirectory: './coverage/raw/default',
+      reporter: ['json'],
     },
     pool: 'forks',
   },

From e97ead277828f65e45dd6f902828718350ec2f2c Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Thu, 30 May 2024 11:07:55 +0900
Subject: [PATCH 2/8] Collect coverage

---
 .github/workflows/ci.yml | 50 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7488baba0..aafbff0d8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,6 +12,31 @@ on:
       - 'LICENSE'
 
 jobs:
+  coverage:
+    name: 'Coverage'
+    runs-on: ubuntu-latest
+    needs:
+      # deno excluded because it does not contain Deno-specific coverage
+      # bun excluded because it does use vitest for testing
+      - main
+      - fastly
+      - node
+      - wrangler
+      - lambda
+      - lambda-edge
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/download-artifact@v4
+        with:
+          pattern: coverage-*
+          merge-multiple: true
+          path: ./coverage
+      - uses: codecov/codecov-action@v4
+        with:
+          fail_ci_if_error: true
+          directory: ./coverage
+          token: ${{ secrets.CODECOV_TOKEN }}
+
   main:
     name: 'Main'
     runs-on: ubuntu-latest
@@ -28,6 +53,10 @@ jobs:
       - run: bun run lint
       - run: bun run build
       - run: bun run test
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-main
+          path: coverage/
 
   jsr-dry-run:
     name: "Checking if it's valid for JSR"
@@ -70,6 +99,10 @@ jobs:
       - run: bun install
       - run: bun run build
       - run: bun run test:fastly
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-fastly
+          path: coverage/
 
   node:
     name: 'Node.js v${{ matrix.node }}'
@@ -86,6 +119,11 @@ jobs:
       - run: bun install
       - run: bun run build
       - run: bun run test:node
+      - uses: actions/upload-artifact@v4
+        if: matrix.node == '22.x'
+        with:
+          name: coverage-node
+          path: coverage/
 
   wrangler:
     name: 'Cloudflare Workers'
@@ -96,6 +134,10 @@ jobs:
       - run: bun install
       - run: bun run build
       - run: bun run test:wrangler
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-wrangler
+          path: coverage/
 
   lambda:
     name: 'AWS Lambda'
@@ -106,6 +148,10 @@ jobs:
       - run: bun install
       - run: bun run build
       - run: bun run test:lambda
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-lambda
+          path: coverage/
 
   lambda-edge:
     name: 'Lambda@Edge'
@@ -116,3 +162,7 @@ jobs:
       - run: bun install --frozen-lockfile
       - run: bun run build
       - run: bun run test:lambda-edge
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-lambda-edge
+          path: coverage/

From f7e390962108cb5cdcfeb644ba96f64fc306325b Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Thu, 30 May 2024 11:57:33 +0900
Subject: [PATCH 3/8] Exclude test-only files

---
 vitest.config.ts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/vitest.config.ts b/vitest.config.ts
index 4065d762b..dc46f7543 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -16,6 +16,13 @@ export default defineConfig({
       provider: 'v8',
       reportsDirectory: './coverage/raw/default',
       reporter: ['json'],
+      exclude: [
+        ...(configDefaults.coverage.exclude ?? []),
+        'benchmarks',
+        'runtime_tests',
+        'build.ts',
+        'src/test-utils',
+      ]
     },
     pool: 'forks',
   },

From d63b0f95f78577235c763b6c9782840a977d9771 Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Thu, 30 May 2024 12:19:07 +0900
Subject: [PATCH 4/8] update comment

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aafbff0d8..9d91c70be 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,7 +17,7 @@ jobs:
     runs-on: ubuntu-latest
     needs:
       # deno excluded because it does not contain Deno-specific coverage
-      # bun excluded because it does use vitest for testing
+      # bun excluded because it uses built-in test tool which does not support coverage in v8/istanbul format.
       - main
       - fastly
       - node

From ecff904f3d1c65db1155b990020a6e13039d7a5e Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Thu, 30 May 2024 12:25:10 +0900
Subject: [PATCH 5/8] exclude types

---
 vitest.config.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/vitest.config.ts b/vitest.config.ts
index dc46f7543..575f1e112 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -22,6 +22,7 @@ export default defineConfig({
         'runtime_tests',
         'build.ts',
         'src/test-utils',
+        'src/**/types.ts', // types are compile-time only, so their coverage cannot be measured
       ]
     },
     pool: 'forks',

From 3f1990ecbe677806cc61545df90689f6361231f0 Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Fri, 31 May 2024 13:57:05 +0900
Subject: [PATCH 6/8] Add config

---
 codecov.yml | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 codecov.yml

diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 000000000..b4889fe95
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,13 @@
+# Edit "test.coverage.exclude" option in vitest.config.ts to exclude specific files from coverage reports.
+# We can also use "ignore" option in codecov.yml, but it is not recognized by vitest, so results may differ on local.
+
+coverage:
+  status:
+    patch:
+      default:
+        target: 80%
+        informational: true # Don't fail the build even if coverage is below target
+    project:
+      default:
+        target: 75%
+        threshold: 1%

From adb9d8a8858e8cd7c3ff8b8f15719ea0f838838b Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Fri, 31 May 2024 14:01:33 +0900
Subject: [PATCH 7/8] Update bun comment

---
 .github/workflows/ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9d91c70be..c4b2c2f23 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,6 +18,7 @@ jobs:
     needs:
       # deno excluded because it does not contain Deno-specific coverage
       # bun excluded because it uses built-in test tool which does not support coverage in v8/istanbul format.
+      # refer https://github.com/oven-sh/bun/issues/4015
       - main
       - fastly
       - node

From a0f7f3c9fd53e0ee579086c268437303689cf918 Mon Sep 17 00:00:00 2001
From: exoego <ytatsuno.jp@gmail.com>
Date: Fri, 31 May 2024 14:03:39 +0900
Subject: [PATCH 8/8] Generate coverage in Deno

---
 .github/workflows/ci.yml | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c4b2c2f23..ff3f3e093 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,7 +16,6 @@ jobs:
     name: 'Coverage'
     runs-on: ubuntu-latest
     needs:
-      # deno excluded because it does not contain Deno-specific coverage
       # bun excluded because it uses built-in test tool which does not support coverage in v8/istanbul format.
       # refer https://github.com/oven-sh/bun/issues/4015
       - main
@@ -77,9 +76,13 @@ jobs:
       - uses: denoland/setup-deno@v1
         with:
           deno-version: v1.x
-      - run: env NAME=Deno deno test --allow-read --allow-env --allow-write -c runtime_tests/deno/deno.json runtime_tests/deno
-      - run: deno test -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx
-      - run: deno test -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx
+      - run: env NAME=Deno deno test --coverage=coverage/raw/deno-runtime --allow-read --allow-env --allow-write -c runtime_tests/deno/deno.json runtime_tests/deno
+      - run: deno test -c runtime_tests/deno-jsx/deno.precompile.json --coverage=coverage/raw/deno-precompile-jsx runtime_tests/deno-jsx
+      - run: deno test -c runtime_tests/deno-jsx/deno.react-jsx.json --coverage=coverage/raw/deno-react-jsx runtime_tests/deno-jsx
+      - uses: actions/upload-artifact@v4
+        with:
+          name: coverage-deno
+          path: coverage/
 
   bun:
     name: 'Bun'