Skip to content

Commit ebe373e

Browse files
committed
test: added unit tests for testable code
1 parent a558aed commit ebe373e

28 files changed

Lines changed: 2532 additions & 430 deletions

.githooks/pre-commit

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,25 @@ else
139139
printf "${RED}Composer audit failed${NC}\n"
140140
fi
141141

142+
# add pest unit tests. stopping the commit if they fail
143+
HAS_PEST=false
144+
PEST="./vendor/bin/pest"
145+
if [ -x $PEST ]; then
146+
HAS_PEST=true
147+
fi
148+
printf "${YELLOW}Pest Unit Tests${NC}\n"
149+
if $HAS_PEST; then
150+
if time exec $PEST --testdox --colors=always; then
151+
# All good, also re-generate clover.xml
152+
$PEST --coverage-clover clover.xml
153+
printf "${GREEN}Pest tests passed${NC}\n"
154+
else
155+
PASS=false
156+
fi
157+
else
158+
printf "\npest is required. Install it with:\n\n ddev composer require --dev pestphp/pest\n\n"
159+
fi
160+
142161
END_TIME=$(date +%s) # Record the end time
143162
DURATION=$((END_TIME - START_TIME)) # Calculate the duration
144163

.github/dependabot.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
9+
# Maintain dependencies for GitHub Actions
10+
- package-ecosystem: "github-actions"
11+
directory: "/"
12+
schedule:
13+
interval: "weekly"
14+
15+
# Maintain dependencies for Composer
16+
- package-ecosystem: "composer"
17+
directory: "/"
18+
schedule:
19+
interval: "weekly"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Code Coverage
2+
on:
3+
push:
4+
# only trigger if theres a change in src/ directory
5+
paths:
6+
- '.github/workflows/code-coverage.yml'
7+
- 'clover.xml'
8+
pull_request:
9+
paths:
10+
- '.github/workflows/code-coverage.yml'
11+
- 'clover.xml'
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: write
16+
jobs:
17+
run:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup PHP
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: '8.4'
27+
28+
- name: Generate code coverage badge
29+
run: php bin/generate-coverage-badge.php clover.xml coverage.svg
30+
31+
- name: Commit badge
32+
run: |
33+
git config --global user.name 'github-actions[bot]'
34+
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
35+
git add coverage.svg
36+
git commit -am "coverage.svg badge updated" --no-verify
37+
git push --no-verify
38+
continue-on-error: true # do not fail if nothing changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/vendor/
2-
/tests/examples/
2+
/tests/examples/
3+
/coverage-report/

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ Then run the tests:
8686
./vendor/bin/pest
8787
```
8888

89-
### Test Structure
90-
91-
- `tests/Feature/DeleteMigrationTest.php` - Tests the delete migration generation functionality
92-
- `tests/Feature/ContentTypeListenerTest.php` - Unit tests for the ContentTypeListener class
89+
### Coverage Report
90+
You can also generate a coverage report by running the following command.
91+
```
92+
XDEBUG_MODE=coverage vendor/bin/pest --coverage-html=coverage-report
93+
```
9394

9495
## Roadmap
9596
* Allow admins to execute pending migrations in the admin panel

bin/generate-coverage-badge.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$cloverPath = $argv[1] ?? 'clover.xml';
6+
$outputPath = $argv[2] ?? 'coverage.svg';
7+
8+
if (!is_file($cloverPath)) {
9+
fwrite(\STDERR, "Clover report not found: {$cloverPath}\n");
10+
exit(1);
11+
}
12+
13+
libxml_use_internal_errors(true);
14+
$xml = simplexml_load_file($cloverPath);
15+
if ($xml === false) {
16+
fwrite(\STDERR, "Failed to parse clover XML: {$cloverPath}\n");
17+
foreach (libxml_get_errors() as $error) {
18+
fwrite(\STDERR, trim($error->message) . "\n");
19+
}
20+
exit(1);
21+
}
22+
23+
$metrics = $xml->project->metrics;
24+
if ($metrics === null) {
25+
fwrite(\STDERR, "Clover XML is missing /coverage/project/metrics\n");
26+
exit(1);
27+
}
28+
29+
$statements = (int) ($metrics['statements'] ?? 0);
30+
$coveredStatements = (int) ($metrics['coveredstatements'] ?? 0);
31+
32+
$percent = 0;
33+
if ($statements > 0) {
34+
$percent = (int) round(($coveredStatements / $statements) * 100);
35+
}
36+
37+
$percent = max(0, min(100, $percent));
38+
39+
// Match the typical shields.io color thresholds.
40+
$color = '#e05d44'; // red
41+
if ($percent >= 90) {
42+
$color = '#4c1'; // green
43+
} elseif ($percent >= 50) {
44+
$color = '#dfb317'; // yellow
45+
}
46+
47+
$percentText = $percent . ' %';
48+
49+
$svg = <<<SVG
50+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="108" height="20" role="img">
51+
<linearGradient id="s" x2="0" y2="100%">
52+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
53+
<stop offset="1" stop-opacity=".1"/>
54+
</linearGradient>
55+
<clipPath id="r">
56+
<rect width="108" height="20" rx="3" fill="#fff"/>
57+
</clipPath>
58+
<g clip-path="url(#r)">
59+
<rect width="63" height="20" fill="#555"/>
60+
<rect x="63" width="45" height="20" fill="{$color}"/>
61+
<rect width="108" height="20" fill="url(#s)"/>
62+
</g>
63+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
64+
<text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">coverage</text>
65+
<text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="530">coverage</text>
66+
<text aria-hidden="true" x="850" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">{$percentText}</text>
67+
<text x="850" y="140" transform="scale(.1)" fill="#fff" textLength="350">{$percentText}</text>
68+
</g>
69+
</svg>
70+
SVG;
71+
72+
if (file_put_contents($outputPath, $svg) === false) {
73+
fwrite(\STDERR, "Failed to write badge: {$outputPath}\n");
74+
exit(1);
75+
}

0 commit comments

Comments
 (0)