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
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,45 @@ jobs:

- name: Run PHPStan
run: composer phpstan

coverage:
name: Coverage
runs-on: ubuntu-22.04
timeout-minutes: 15

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: xdebug
tools: composer:v2

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'

- name: Install Composer dependencies
run: composer update --no-interaction --prefer-dist --no-progress

- name: Install Node.js dependencies
run: npm install

- name: Run PHP coverage
run: composer coverage

- name: Run JavaScript coverage
run: npm run test:coverage

- name: Upload coverage reports
uses: actions/upload-artifact@v4
with:
name: coverage-reports
if-no-files-found: error
path: |
build/logs/phpunit-clover.xml
build/coverage/jest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.idea
.phpunit.cache/
build/
coverage/
vendor
composer.lock

Expand Down
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Local path: `/Volumes/SRC/JsFormValidatorBundle`
- The JavaScript job runs on Node `22` with PHP `8.3`.
- The JavaScript job installs Cypress system dependencies, then runs `composer update`, `npm install`, and `npm test`.
- The PHPStan job runs on PHP `8.3`, installs dependencies with `composer update`, warms the Symfony test cache, and runs `composer phpstan`.
- The Coverage job runs on PHP `8.3` with Xdebug and Node `22`, then runs `composer coverage` and `npm run test:coverage`.
- Coverage thresholds currently enforced by `tools/check-clover-coverage.php`: PHP line coverage at least `50%`, JavaScript line coverage at least `60%`.
- The old `.travis.yml` file was removed.
- `README.md` was updated to use a GitHub Actions badge and test instructions instead of Travis CI references.
- `package.json` no longer advertises the old Travis CI badge in the package description.
Expand All @@ -28,7 +30,9 @@ Local path: `/Volumes/SRC/JsFormValidatorBundle`

- `php /tmp/jsfv-composer.phar test` passes: `5 tests, 18 assertions`.
- `php /tmp/jsfv-composer.phar phpstan` runs PHPStan with `phpstan.neon`.
- `php /tmp/jsfv-composer.phar coverage` generates PHP Clover coverage and checks the `50%` line threshold.
- `npm test` passes: Jest `197 tests`; Cypress e2e `16 tests`.
- `npm run test:coverage` generates Jest coverage and checks the `60%` line threshold.
- The local `composer` shim is broken with `Could not open input file: /Users/ton/bin/composer`, so use `/tmp/jsfv-composer.phar` locally if needed.

## GitHub Checks Note
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,24 @@ Run PHPStan static analysis:
composer phpstan
```

Run PHP coverage:

```bash
composer coverage
```

Run the JavaScript unit tests and Cypress browser smoke test:

```bash
npm test
```

Run JavaScript coverage:

```bash
npm run test:coverage
```

Useful local checks:

```bash
Expand Down
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
},

"scripts": {
"coverage": [
"XDEBUG_MODE=coverage phpunit --coverage-clover build/logs/phpunit-clover.xml --coverage-text --only-summary-for-coverage-text",
"php tools/check-clover-coverage.php build/logs/phpunit-clover.xml 50 PHP"
],
"phpstan": [
"APP_ENV=test APP_DEBUG=1 php Tests/app/bin/console cache:warmup --env=test",
"phpstan analyse --memory-limit=1G"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"scripts": {
"test": "npm run test:unit && npm run test:e2e",
"test:unit": "jest",
"test:coverage": "jest --coverage --coverageReporters=text-summary --coverageReporters=clover --coverageReporters=lcov --coverageDirectory=build/coverage/jest && php tools/check-clover-coverage.php build/coverage/jest/clover.xml 60 JavaScript",
"test:e2e": "npm run test:e2e:build && start-server-and-test test:e2e:serve http://127.0.0.1:8000 test:e2e:run",
"test:e2e:build": "php Tests/app/bin/console assets:install Tests/app/public --env=test && npm --prefix Tests/app install && npm --prefix Tests/app run build",
"test:e2e:serve": "APP_ENV=test APP_DEBUG=1 php -S 127.0.0.1:8000 -t Tests/app/public Tests/app/public/index.php",
Expand Down
45 changes: 45 additions & 0 deletions tools/check-clover-coverage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

if (4 !== $argc) {
fwrite(STDERR, "Usage: php tools/check-clover-coverage.php <clover.xml> <min-percent> <label>\n");
exit(2);
}

$file = $argv[1];
$minimum = (float) $argv[2];
$label = $argv[3];

if (!is_file($file)) {
fwrite(STDERR, sprintf("%s coverage report not found: %s\n", $label, $file));
exit(1);
}

$xml = simplexml_load_file($file);
if (false === $xml || !isset($xml->project->metrics)) {
fwrite(STDERR, sprintf("%s coverage report is not valid Clover XML: %s\n", $label, $file));
exit(1);
}

$metrics = $xml->project->metrics;
$statements = (int) $metrics['statements'];
$coveredStatements = (int) $metrics['coveredstatements'];

if (0 === $statements) {
fwrite(STDERR, sprintf("%s coverage report has no statements.\n", $label));
exit(1);
}

$coverage = $coveredStatements / $statements * 100;
printf(
"%s line coverage: %.2f%% (%d/%d), minimum: %.2f%%\n",
$label,
$coverage,
$coveredStatements,
$statements,
$minimum
);

if ($coverage + 0.00001 < $minimum) {
fwrite(STDERR, sprintf("%s line coverage is below the required minimum.\n", $label));
exit(1);
}
Loading