ci: add test coverage (#2073)

* ci: add test coverage

* ci: add test coverage
This commit is contained in:
Daniel Salazar
2025-12-01 08:56:44 -08:00
committed by GitHub
parent d978c37e0b
commit c77272012d
5 changed files with 235 additions and 8 deletions

View File

@@ -22,13 +22,62 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- name: Backend Tests
- name: Backend Tests (with coverage)
run: |
rm package-lock.json
npm install -g npm@latest
npm install
npm run build
npm run test:backend
npm run test:backend -- --coverage
- name: Upload backend coverage report
if: ${{ always() && hashFiles('coverage/**/coverage-summary.json') != '' }}
uses: actions/upload-artifact@v4
with:
name: backend-coverage-${{ matrix.node-version }}
path: coverage
retention-days: 5
- name: Publish backend coverage summary
if: ${{ always() && matrix.node-version == '22.x' }}
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const globModule = require('glob');
const matches = globModule.sync('coverage/**/coverage-summary.json', {
cwd: process.cwd(),
ignore: ['**/node_modules/**'],
});
if (!matches.length) {
core.warning('Coverage summary not found (expected coverage/**/coverage-summary.json). Did Vitest run with --coverage and include the json-summary reporter?');
return;
}
const summaryPath = path.resolve(matches[0]);
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8'));
const metrics = ['lines', 'statements', 'branches', 'functions']
.map((key) => ({
label: key.charAt(0).toUpperCase() + key.slice(1),
...summary.total[key],
}));
core.summary
.addHeading('Backend coverage')
.addTable([
['Metric', 'Covered', 'Total', 'Pct'],
...metrics.map(({ label, covered, total, pct }) => [
label,
`${covered}`,
`${total}`,
`${pct}%`,
]),
])
.addRaw('Full HTML report is available in the uploaded `backend-coverage-${{ matrix.node-version }}` artifact.')
.write();
api-test:
name: API tests (node env, api-test)

5
.gitignore vendored
View File

@@ -63,4 +63,7 @@ AGENTS.md
.roo
# source maps
*.map
*.map
coverage/

163
package-lock.json generated
View File

@@ -39,6 +39,8 @@
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.46.1",
"@typescript-eslint/parser": "^8.46.1",
"@vitest/coverage-v8": "^4.0.14",
"@vitest/ui": "^4.0.14",
"chalk": "^4.1.0",
"clean-css": "^5.3.2",
"dotenv": "^16.4.5",
@@ -1272,6 +1274,16 @@
"node": ">=6.9.0"
}
},
"node_modules/@bcoe/v8-coverage": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
"integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@bufbuild/protobuf": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.1.tgz",
@@ -6425,6 +6437,13 @@
"node": ">=18"
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.29",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
"integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
"dev": true,
"license": "MIT"
},
"node_modules/@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
@@ -8145,6 +8164,53 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vitest/coverage-v8": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.14.tgz",
"integrity": "sha512-EYHLqN/BY6b47qHH7gtMxAg++saoGmsjWmAq9MlXxAz4M0NcHh9iOyKhBZyU4yxZqOd8Xnqp80/5saeitz4Cng==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
"@vitest/utils": "4.0.14",
"ast-v8-to-istanbul": "^0.3.8",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
"istanbul-lib-source-maps": "^5.0.6",
"istanbul-reports": "^3.2.0",
"magicast": "^0.5.1",
"obug": "^2.1.1",
"std-env": "^3.10.0",
"tinyrainbow": "^3.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@vitest/browser": "4.0.14",
"vitest": "4.0.14"
},
"peerDependenciesMeta": {
"@vitest/browser": {
"optional": true
}
}
},
"node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
"integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.23",
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@vitest/expect": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.14.tgz",
@@ -8252,6 +8318,36 @@
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/ui": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.0.14.tgz",
"integrity": "sha512-fvDz8o7SQpFLoSBo6Cudv+fE85/fPCkwTnLAN85M+Jv7k59w2mSIjT9Q5px7XwGrmYqqKBEYxh/09IBGd1E7AQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/utils": "4.0.14",
"fflate": "^0.8.2",
"flatted": "^3.3.3",
"pathe": "^2.0.3",
"sirv": "^3.0.2",
"tinyglobby": "^0.2.15",
"tinyrainbow": "^3.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"vitest": "4.0.14"
}
},
"node_modules/@vitest/ui/node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"dev": true,
"license": "MIT"
},
"node_modules/@vitest/utils": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.14.tgz",
@@ -8928,6 +9024,25 @@
"node": "*"
}
},
"node_modules/ast-v8-to-istanbul": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz",
"integrity": "sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.31",
"estree-walker": "^3.0.3",
"js-tokens": "^9.0.1"
}
},
"node_modules/ast-v8-to-istanbul/node_modules/js-tokens": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"dev": true,
"license": "MIT"
},
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
@@ -15052,6 +15167,18 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/magicast": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz",
"integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.5",
"@babel/types": "^7.28.5",
"source-map-js": "^1.2.1"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -15465,6 +15592,16 @@
"node": ">=4"
}
},
"node_modules/mrmime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
"integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -18297,6 +18434,21 @@
"node": ">=8"
}
},
"node_modules/sirv": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
"integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/slash": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
@@ -19380,6 +19532,16 @@
"url": "https://github.com/sponsors/Borewit"
}
},
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/touch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
@@ -19899,6 +20061,7 @@
"integrity": "sha512-d9B2J9Cm9dN9+6nxMnnNJKJCtcyKfnHj15N6YNJfaFHRLua/d3sRKU9RuKmO9mB0XdFtUizlxfz/VPbd3OxGhw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/expect": "4.0.14",
"@vitest/mocker": "4.0.14",

View File

@@ -17,6 +17,8 @@
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.46.1",
"@typescript-eslint/parser": "^8.46.1",
"@vitest/coverage-v8": "^4.0.14",
"@vitest/ui": "^4.0.14",
"chalk": "^4.1.0",
"clean-css": "^5.3.2",
"dotenv": "^16.4.5",
@@ -40,9 +42,10 @@
"yaml": "^2.8.1"
},
"scripts": {
"test": "npx mocha src/phoenix/test && npx vitest run src/backend && node src/backend/tools/test.mjs",
"test": "npx mocha src/phoenix/test && npx vitest run --config=src/backend/vitest.config.ts && node src/backend/tools/test.mjs",
"test:puterjs-api": "vitest run tests/puterJsApiTests",
"test:backend": "npm run build:ts; vitest run --config=src/backend/vitest.config.ts src/backend",
"test:backend": "npm run build:ts; vitest run --config=src/backend/vitest.config.ts",
"test:backend-coverage": "npm run build:ts; vitest run --config=src/backend/vitest.config.ts",
"start=gui": "nodemon --exec \"node dev-server.js\" ",
"start": "node ./tools/run-selfhosted.js",
"prestart": "npm run build:ts",
@@ -92,4 +95,4 @@
"engines": {
"node": ">=20.19.5"
}
}
}

View File

@@ -8,9 +8,18 @@ export default defineConfig(({ mode }) => ({
environment: 'jsdom',
setupFiles: [],
coverage: {
reporter: ['text', 'json', 'html'],
exclude: [],
provider: 'v8',
reporter: ['text', 'json', 'json-summary', 'html', 'lcov'],
include: ['src/backend/**/*.js', 'src/backend/**/*.mjs', 'src/backend/**/*.ts', 'src/backend/**/*.ts'],
exclude: [
'**/types/**',
'**/constants/**',
'**/*.d.ts',
'**/dist/**',
'**/*.min.*',
],
},
env: loadEnv(mode, '', 'PUTER_'),
include: ['src/backend/**/*.test.ts', 'src/backend/**/*.test.js']
},
}));