Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
368 commits
Select commit Hold shift + click to select a range
2b12057
Add IAM search controller coverage
roncodes Jul 17, 2026
74e05af
Add middleware security contract coverage
roncodes Jul 17, 2026
45712ce
Add builder expansion coverage
roncodes Jul 17, 2026
98a1779
Add route expansion coverage
roncodes Jul 17, 2026
7f583ad
Add report controller coverage
roncodes Jul 17, 2026
2cfdcb8
Add chat channel controller coverage
roncodes Jul 17, 2026
4ce736f
Add template controller coverage
roncodes Jul 17, 2026
7887f33
Add API credential controller coverage
roncodes Jul 17, 2026
0dbc2d3
Add notification controller coverage
roncodes Jul 17, 2026
ba0c955
Add two factor controller coverage
roncodes Jul 17, 2026
be5bc5c
Add role controller coverage
roncodes Jul 17, 2026
83946f7
Add policy controller coverage
roncodes Jul 17, 2026
e79832d
Add group controller coverage
roncodes Jul 17, 2026
eff5632
Add organization API coverage
roncodes Jul 17, 2026
9bda698
Add resource response coverage
roncodes Jul 17, 2026
09cf3e4
Add role resource coverage
roncodes Jul 17, 2026
7e0ef91
Add fleetbase configuration middleware coverage
roncodes Jul 17, 2026
1455184
Add API request logging middleware coverage
roncodes Jul 17, 2026
5b785de
Add public chat channel API coverage
roncodes Jul 18, 2026
052ee0e
Add public file API coverage
roncodes Jul 18, 2026
246586f
Add internal request validation coverage
roncodes Jul 18, 2026
e97ab39
Add public comment API coverage
roncodes Jul 18, 2026
82f772d
Add onboarding verification coverage
roncodes Jul 18, 2026
7ef443e
Add concrete filter coverage
roncodes Jul 18, 2026
62fe634
Add request and resource contract coverage
roncodes Jul 18, 2026
df344e3
Add auth and schedule filter coverage
roncodes Jul 18, 2026
0fd2793
Add trait and resource coverage
roncodes Jul 18, 2026
319dcbb
Add HTTP filter and request coverage
roncodes Jul 18, 2026
6373c45
Add scope middleware and log filter coverage
roncodes Jul 18, 2026
f76d0db
Add array request and chat filter coverage
roncodes Jul 18, 2026
4e4f2d0
Add session request and metric coverage
roncodes Jul 18, 2026
cec9b71
Cover guard filter and scheduling contracts
roncodes Jul 18, 2026
490352b
Cover authorization and request contracts
roncodes Jul 18, 2026
8556b16
Cover lightweight HTTP and purge contracts
roncodes Jul 18, 2026
6c8a592
Cover purge internals and tenant filters
roncodes Jul 18, 2026
c52b531
Cover lightweight provider and resource contracts
roncodes Jul 18, 2026
3140083
Cover admin maintenance commands
roncodes Jul 18, 2026
ab068e2
Cover database backup commands
roncodes Jul 18, 2026
f359f6d
Cover webhook job and extension contracts
roncodes Jul 18, 2026
d9865b8
Cover developer search and policy traits
roncodes Jul 18, 2026
0de87fc
Cover push notification and basic auth contracts
roncodes Jul 18, 2026
f4c159c
Cover API model cache trait contracts
roncodes Jul 18, 2026
bda7027
Cover API controller trait contracts
roncodes Jul 18, 2026
70ed987
Cover user and extension controller contracts
roncodes Jul 18, 2026
ad7c24f
Cover scheduled report execution contracts
roncodes Jul 18, 2026
4dc8f95
Expand scheduling service coverage
roncodes Jul 18, 2026
04d9012
Cover APN push notification contracts
roncodes Jul 18, 2026
a5f6311
Cover chat participant broadcast events
roncodes Jul 18, 2026
c917a68
Cover role controller sync contracts
roncodes Jul 18, 2026
4defd68
Cover webhook endpoint controller contracts
roncodes Jul 18, 2026
3e827c6
Cover resource lifecycle webhook listener
roncodes Jul 18, 2026
097b697
Cover create permissions command flow
roncodes Jul 18, 2026
38e7b9d
Cover auth verification code success flows
roncodes Jul 18, 2026
cf555c3
Cover resource collection response shaping
roncodes Jul 18, 2026
6b59ed8
Expand utils helper coverage
roncodes Jul 18, 2026
12ed358
Cover sql dumper streaming flow
roncodes Jul 18, 2026
2bd98a0
Cover company admin organization flows
roncodes Jul 18, 2026
955d7b9
Cover response expansion contracts
roncodes Jul 18, 2026
44afd61
Cover verification code delivery contracts
roncodes Jul 18, 2026
e897aad
Cover base model lookup contracts
roncodes Jul 18, 2026
a4278f9
Cover auth login and bootstrap contracts
roncodes Jul 18, 2026
2f32684
Cover user current account contracts
roncodes Jul 18, 2026
0915557
Cover internal file upload contracts
roncodes Jul 18, 2026
dfeb4e3
Cover expiry scope request contracts
roncodes Jul 18, 2026
ab09d2a
Cover auth request and seeder command contracts
roncodes Jul 18, 2026
c8eccd1
Cover provider and auth verifier contracts
roncodes Jul 18, 2026
ebc0c30
Cover recovery command and Apple verifier branches
roncodes Jul 18, 2026
5e3b893
Cover schedule template and verification fallback contracts
roncodes Jul 18, 2026
1111c13
Cover report and user controller edge contracts
roncodes Jul 18, 2026
5bc5b64
Cover company admin lifecycle contracts
roncodes Jul 18, 2026
f7e2153
Cover user invitation contracts
roncodes Jul 18, 2026
ff060fb
Cover auth administration contracts
roncodes Jul 18, 2026
c4567a1
Cover API model behavior contracts
roncodes Jul 18, 2026
b4000b3
Cover lookup controller contracts
roncodes Jul 18, 2026
8dd8fdf
Cover request validation and filter contracts
roncodes Jul 18, 2026
287ebaf
Cover shared utility lookup contracts
roncodes Jul 18, 2026
58f6eff
Fix derived class coverage summary
roncodes Jul 18, 2026
2aa65cb
Cover utility formatting edge cases
roncodes Jul 18, 2026
ded0552
Cover FCM push notification payloads
roncodes Jul 18, 2026
d33734d
Cover extension seeder command flow
roncodes Jul 18, 2026
4878b88
Cover comment filters and API credential tracking
roncodes Jul 18, 2026
1e629ab
Expand report resource and audit log coverage
roncodes Jul 18, 2026
ac6a1c7
Cover presence and policy lookup contracts
roncodes Jul 18, 2026
dc41b5b
Cover expandable runtime method registration
roncodes Jul 18, 2026
3816e6a
Cover data purger safety contracts
roncodes Jul 18, 2026
c3ebf25
Cover chat log lifecycle contracts
roncodes Jul 18, 2026
859e73b
Cover core provider expansion contracts
roncodes Jul 18, 2026
61f8e5e
Cover group controller error and export contracts
roncodes Jul 18, 2026
d381a0b
Cover queue status sqs health checks
roncodes Jul 18, 2026
fe913f9
Cover recovery prompt lookup flows
roncodes Jul 18, 2026
1a25ba2
Cover user controller invite and removal edges
roncodes Jul 18, 2026
77d1cb1
Cover schedule service lifecycle contracts
roncodes Jul 18, 2026
db0236a
Cover policy trait edge contracts
roncodes Jul 18, 2026
cdd52d3
Cover chat receipt error responses
roncodes Jul 18, 2026
67aabcd
Cover basic auth middleware response contracts
roncodes Jul 18, 2026
0df61d4
Cover report query execution contracts
roncodes Jul 18, 2026
f5c483f
Cover onboarding account creation contracts
roncodes Jul 18, 2026
5ddb233
Cover builder expansion query edge cases
roncodes Jul 18, 2026
3f32949
Cover SMPP gateway transport edge cases
roncodes Jul 18, 2026
f04f1b0
Cover user controller invite and cache branches
roncodes Jul 18, 2026
5464b59
Cover auth verification success flows
roncodes Jul 18, 2026
1c50080
Cover notification registry dispatch flows
roncodes Jul 18, 2026
08400fa
Cover policy controller error contracts
roncodes Jul 18, 2026
4e07bcd
Cover schedule filter edge contracts
roncodes Jul 18, 2026
c07e6e9
Cover category filter parent contracts
roncodes Jul 18, 2026
fbe2b9d
Clarify class coverage summary
roncodes Jul 18, 2026
27fb4e7
Cover two factor auth edge flows
roncodes Jul 18, 2026
29e3366
Cover company controller settings and extensions
roncodes Jul 18, 2026
c0cda23
Cover scheduling model contracts
roncodes Jul 18, 2026
d4ff904
Cover template model and search contracts
roncodes Jul 18, 2026
0173358
Cover phone parsing fallback contracts
roncodes Jul 18, 2026
bdd76e6
Cover report model and subject contracts
roncodes Jul 18, 2026
99d6498
Cover install notification command contracts
roncodes Jul 18, 2026
4bc96e0
Cover resource collection response branches
roncodes Jul 18, 2026
33933ec
Cover MessageBird SMS failure contracts
roncodes Jul 18, 2026
8ce25f1
Cover CallPro SMS provider contracts
roncodes Jul 18, 2026
e5b444e
Cover lifecycle webhook listener failure contracts
roncodes Jul 18, 2026
e5cc7fb
Cover settings save configuration contracts
roncodes Jul 18, 2026
eece9ec
Cover report controller saved report contracts
roncodes Jul 18, 2026
9693d9d
Cover auth support permission contracts
roncodes Jul 18, 2026
c7dc1de
Cover core provider boot contracts
roncodes Jul 18, 2026
9a9ab59
Cover chat message error contracts
roncodes Jul 18, 2026
6a51c86
Cover fleetbase resource contracts
roncodes Jul 18, 2026
eb0aa03
Cover scheduling relation contracts
roncodes Jul 18, 2026
06c145c
Cover sandbox migration command contracts
roncodes Jul 18, 2026
31d00fd
Cover public id trait edge cases
roncodes Jul 18, 2026
bd54d98
Cover API event filter date branches
roncodes Jul 18, 2026
a9c8dce
Cover report query validation messages
roncodes Jul 18, 2026
fb51149
Cover user and schedule item filter contracts
roncodes Jul 18, 2026
56b8db7
Cover company filter edge contracts
roncodes Jul 18, 2026
d4df572
Cover utility edge contracts
roncodes Jul 18, 2026
8769f96
Cover API model filter operators
roncodes Jul 18, 2026
690e9b2
Cover user record mutation contracts
roncodes Jul 18, 2026
22c9b54
Cover public file API failure contracts
roncodes Jul 18, 2026
2fc3e9c
Cover scheduling and data purge safety contracts
roncodes Jul 18, 2026
27ecf22
Cover basic auth middleware token branches
roncodes Jul 18, 2026
e9f580b
Cover exception handler response contracts
roncodes Jul 18, 2026
a048ab3
Cover template render edge contracts
roncodes Jul 18, 2026
0c0f720
Cover utility helper edge contracts
roncodes Jul 18, 2026
799a67f
Cover socket cluster service lifecycle
roncodes Jul 18, 2026
f445a4a
Cover blade expansion helper contracts
roncodes Jul 18, 2026
dba872e
Cover builder expansion directive contracts
roncodes Jul 18, 2026
bf20a9a
Cover webhook job transport failure contracts
roncodes Jul 18, 2026
47b6c4c
Cover schedule template rrule edge contracts
roncodes Jul 18, 2026
5177876
Cover shared utility deletion contracts
roncodes Jul 18, 2026
e20fa0b
Cover auth sms verification send contracts
roncodes Jul 18, 2026
5eeb728
Cover data purger safety branches
roncodes Jul 18, 2026
3e5399a
Cover resource lifecycle event edge cases
roncodes Jul 18, 2026
b317285
Cover throttle middleware limit branches
roncodes Jul 18, 2026
3753488
Cover api model cache fallback branches
roncodes Jul 18, 2026
92ef772
Cover user model request and company branches
roncodes Jul 18, 2026
4050a09
Cover policy trait guard branches
roncodes Jul 18, 2026
3431da6
Cover internal file resize uploads
roncodes Jul 18, 2026
3d6af1f
Cover utility helper edge cases
roncodes Jul 18, 2026
17ae70a
Cover company model edge cases
roncodes Jul 18, 2026
e22c38e
Cover SMS provider edge cases
roncodes Jul 19, 2026
0364644
Cover image service edge cases
roncodes Jul 19, 2026
c4d8421
Cover sql dumper public dump paths
roncodes Jul 19, 2026
6747dbe
Cover custom value file casts and request auth
roncodes Jul 19, 2026
a0bac15
Cover request expansion and download request contracts
roncodes Jul 19, 2026
4114641
Cover group exports and webhook endpoint contracts
roncodes Jul 19, 2026
80941bf
Cover request filter and setting model gaps
roncodes Jul 19, 2026
97aba0f
Cover comment scheduling and options contracts
roncodes Jul 19, 2026
92bc3b8
Cover filter and admin role command edges
roncodes Jul 19, 2026
582bbdc
Cover reporting query converter and validator edges
roncodes Jul 19, 2026
ae18d29
Cover public chat channel edge contracts
roncodes Jul 19, 2026
eaf82cc
Cover data purger metadata discovery
roncodes Jul 19, 2026
83b70c3
Cover API controller behavior edge contracts
roncodes Jul 19, 2026
2bcc091
Cover query optimizer edge contracts
roncodes Jul 19, 2026
2e067d2
Cover Google verifier success contracts
roncodes Jul 19, 2026
fc7d9a6
Cover activity filter route branches
roncodes Jul 19, 2026
c490264
Cover role controller typed error branches
roncodes Jul 19, 2026
a16dd20
Cover group controller typed error branches
roncodes Jul 19, 2026
932915d
Expand company controller contract coverage
roncodes Jul 19, 2026
878403c
Expand auth reset and impersonation coverage
roncodes Jul 19, 2026
c180d05
Expand Utils coverage contracts
roncodes Jul 19, 2026
d984254
Cover report controller failure contracts
roncodes Jul 19, 2026
66edded
Cover alert model edge contracts
roncodes Jul 19, 2026
b8e31cf
Cover settings controller config contracts
roncodes Jul 19, 2026
841cf69
Cover availability and push notification contracts
roncodes Jul 19, 2026
454c606
Cover user cache and file resolver edge contracts
roncodes Jul 19, 2026
571b537
Cover SMS provider routing edge contracts
roncodes Jul 19, 2026
846b0f1
Cover lifecycle UUID edge contracts
roncodes Jul 25, 2026
99f600a
Cover user authorization proxy contracts
roncodes Jul 25, 2026
0984d5f
Cover controller validation and unauthorized fallback contracts
roncodes Jul 25, 2026
5849e8b
Cover HTTP helpers and prefixed REST routes
roncodes Jul 25, 2026
f7ae7dd
Cover API model cache and utility edge contracts
roncodes Jul 25, 2026
52e6f07
Cover utility and report converter edge contracts
roncodes Jul 25, 2026
21d7488
Cover report query validation error contracts
roncodes Jul 25, 2026
ec6157c
Cover report converter helper contracts
roncodes Jul 25, 2026
45d5391
Cover user invite acceptance edge cases
roncodes Jul 25, 2026
4df9cc4
Cover utility extension discovery contracts
roncodes Jul 25, 2026
8aa83c6
Cover SQL dumper fallback export contracts
roncodes Jul 25, 2026
ba706ef
Cover report schema registry cache contracts
roncodes Jul 25, 2026
6d0ce01
Cover admin metrics fallback contracts
roncodes Jul 25, 2026
6644cc0
Cover report schema registry edge contracts
roncodes Jul 25, 2026
df8f685
Cover user model edge contracts
roncodes Jul 25, 2026
8c4d45a
Cover file model storage contracts
roncodes Jul 25, 2026
8d36de6
Cover expirable and credential model contracts
roncodes Jul 25, 2026
7dc5f80
Cover chat unread and backup failure contracts
roncodes Jul 25, 2026
581f524
Cover purge command fallback deletion
roncodes Jul 25, 2026
e084fe2
Cover public webhook URL validation edges
roncodes Jul 25, 2026
9d6ed05
Cover SMPP SMS validation contracts
roncodes Jul 25, 2026
043911f
Cover template query execution branches
roncodes Jul 25, 2026
897dbfc
Cover model and filter edge contracts
roncodes Jul 25, 2026
f9891b4
Cover cacheable attribute and branch contracts
roncodes Jul 25, 2026
0aff7a8
Cover webhook sync and route overload contracts
roncodes Jul 25, 2026
3ba9d64
Cover query optimizer and setting model edge cases
roncodes Jul 25, 2026
bc774b1
Cover report query error classifications
roncodes Jul 25, 2026
4d07fa7
Cover utility subject and database execution contracts
roncodes Jul 25, 2026
f8be166
Cover SMS provider setting response contracts
roncodes Jul 25, 2026
e530bca
Cover user lifecycle authorization edges
roncodes Jul 25, 2026
1cb76e3
Cover auth token and two factor login paths
roncodes Jul 25, 2026
6526ad9
Cover auth organization contracts
roncodes Jul 25, 2026
5c14e67
Cover user search and export contracts
roncodes Jul 25, 2026
2c6f9d6
Cover report controller error contracts
roncodes Jul 25, 2026
2828029
Cover api model behavior helper contracts
roncodes Jul 25, 2026
5976a32
Cover policy relation mutation contracts
roncodes Jul 25, 2026
24961dd
Cover nested builder sort contracts
roncodes Jul 25, 2026
24e6c83
Expand two factor auth coverage
roncodes Jul 25, 2026
ae68b3f
Cover exception handler fallback contracts
roncodes Jul 25, 2026
9609267
Cover expandable trait fallback contracts
roncodes Jul 25, 2026
ce12920
Cover utility fallback contracts
roncodes Jul 25, 2026
f6a9982
Cover comment relationship contracts
roncodes Jul 25, 2026
f0dbf2e
Cover schedule exception contracts
roncodes Jul 25, 2026
a9663d5
Cover model relationship and scheduling contracts
roncodes Jul 25, 2026
7e0ec9d
Cover model and support edge contracts
roncodes Jul 25, 2026
c894344
Cover reporting and sandbox support branches
roncodes Jul 25, 2026
e1deb81
Cover SQL dumper metadata discovery
roncodes Jul 26, 2026
2828b67
Cover comment controller error responses
roncodes Jul 26, 2026
cc800a4
Cover organization credential fallbacks
roncodes Jul 26, 2026
7625e3a
Cover data purger table discovery fallbacks
roncodes Jul 26, 2026
be909a4
Cover lookup response fallback contracts
roncodes Jul 26, 2026
36d6849
Cover API credential edge contracts
roncodes Jul 26, 2026
543ac6c
Cover telemetry edge contracts
roncodes Jul 26, 2026
0bbbc4b
Cover SMS authentication edge contracts
roncodes Jul 26, 2026
46d1ef9
Cover user controller edge contracts
roncodes Jul 26, 2026
b00f395
Cover settings filesystem edge contracts
roncodes Jul 26, 2026
ccc1c10
Cover settings provider failure contracts
roncodes Jul 26, 2026
8649346
Cover custom field edge contracts
roncodes Jul 26, 2026
4b3ee02
Cover API model behavior edge contracts
roncodes Jul 26, 2026
023c74b
Cover Utils database conversion contracts
roncodes Jul 26, 2026
ca6e73a
Cover focused request rule and trait branches
roncodes Jul 26, 2026
5e374ea
Cover webhook event and resource edge branches
roncodes Jul 26, 2026
a034306
Cover resource pagination and nested response branches
roncodes Jul 26, 2026
e9bdbc1
Cover expansion and country edge contracts
roncodes Jul 26, 2026
302a9c3
Cover route company and phone edge contracts
roncodes Jul 26, 2026
15ef3f8
Reach full backend coverage for core API
roncodes Jul 26, 2026
1d5a0d6
Stabilize user creation response assertion
roncodes Jul 26, 2026
2709b44
Align user controller test schema with user payload
roncodes Jul 26, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
composer.lock
/vendor/
/coverage/
/.fleetbase-id
/.phpunit.cache/
.phpunit.result.cache
.php_cs.cache
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fleetbase/core-api",
"version": "1.6.54",
"version": "1.6.55",
"description": "Core Framework and Resources for Fleetbase API",
"keywords": [
"fleetbase",
Expand Down Expand Up @@ -108,7 +108,7 @@
"test:coverage:clover": "mkdir -p coverage && php scripts/coverage-runner.php --coverage-clover=coverage/clover.xml --colors=always",
"test:lint": "php-cs-fixer fix -v --dry-run",
"test:types": "phpstan analyse --ansi --memory-limit=-1",
"test:unit": "pest --colors=always",
"test:unit": "php -d memory_limit=512M vendor/bin/pest --colors=always",
"test": [
"@test:lint",
"@test:types",
Expand Down
2 changes: 1 addition & 1 deletion scripts/coverage-runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
$_ENV['XDEBUG_MODE'] = 'coverage';
$_SERVER['XDEBUG_MODE'] = 'coverage';

$command = array_merge([PHP_BINARY, $pest], $args);
$command = array_merge([PHP_BINARY, '-d', 'memory_limit=-1', $pest], $args);
} else {
fwrite(STDERR, "No PHP coverage driver is available.\n\n");
fwrite(STDERR, "Install or enable one of:\n");
Expand Down
60 changes: 59 additions & 1 deletion scripts/coverage-summary.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,49 @@ function intMetric(SimpleXMLElement $node, string $name): int
return (int) ($node->metrics[$name] ?? 0);
}

function hasMetric(SimpleXMLElement $node, string $name): bool
{
foreach ($node->metrics->attributes() as $metricName => $value) {
if ($metricName === $name) {
return true;
}
}

return false;
}

function derivedClassCoverageMetrics(SimpleXMLElement $project): array
{
$classes = 0;
$coveredClasses = 0;
$touchedClasses = 0;

foreach ($project->xpath('.//class') ?: [] as $class) {
$statements = intMetric($class, 'statements');
$coveredStatements = intMetric($class, 'coveredstatements');

if ($statements === 0) {
continue;
}

$classes++;

if ($coveredStatements > 0) {
$touchedClasses++;
}

if ($statements > 0 && $coveredStatements === $statements) {
$coveredClasses++;
}
}

return [
'classes' => $classes,
'covered' => $coveredClasses,
'touched' => $touchedClasses,
];
}

$project = $xml->project;
$metrics = $project->metrics;

Expand All @@ -35,6 +78,18 @@ function intMetric(SimpleXMLElement $node, string $name): int
$coveredMethods = (int) ($metrics['coveredmethods'] ?? 0);
$classes = (int) ($metrics['classes'] ?? 0);
$coveredClasses = (int) ($metrics['coveredclasses'] ?? 0);
$classCoverageLabel = 'Class coverage';
$classCoverageNote = '';
$touchedClasses = null;

if (!hasMetric($project, 'coveredclasses')) {
$derivedClasses = derivedClassCoverageMetrics($project);
$classes = $classes ?: $derivedClasses['classes'];
$coveredClasses = $derivedClasses['covered'];
$touchedClasses = $derivedClasses['touched'];
$classCoverageLabel = 'Fully covered class coverage';
$classCoverageNote = ' derived from class statement metrics because Clover omits coveredclasses';
}

$files = [];
$directories = [];
Expand Down Expand Up @@ -96,7 +151,10 @@ function intMetric(SimpleXMLElement $node, string $name): int

printf("Line coverage: %.2f%% (%d/%d statements)\n", coveragePercent($coveredStatements, $statements), $coveredStatements, $statements);
printf("Method coverage: %.2f%% (%d/%d methods)\n", coveragePercent($coveredMethods, $methods), $coveredMethods, $methods);
printf("Class coverage: %.2f%% (%d/%d classes)\n", coveragePercent($coveredClasses, $classes), $coveredClasses, $classes);
printf("%s: %.2f%% (%d/%d classes%s)\n", $classCoverageLabel, coveragePercent($coveredClasses, $classes), $coveredClasses, $classes, $classCoverageNote);
if ($touchedClasses !== null) {
printf("Touched class coverage: %.2f%% (%d/%d classes executed at least once)\n", coveragePercent($touchedClasses, $classes), $touchedClasses, $classes);
}

echo "\nLowest covered directories:\n";
foreach (array_slice($directoryRows, 0, 10) as $row) {
Expand Down
3 changes: 3 additions & 0 deletions src/Auth/AppleVerifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ public static function verifyAppleJwt(string $jwt): bool

// Fetch and cache the Apple public keys
$data = Cache::remember('apple-JWKSet', self::CACHE_DURATION, function () {
// Cache-miss retrieval hits Apple's live JWK endpoint; unit tests inject cached key data.
// @codeCoverageIgnoreStart
$response = (new Client())->get(self::APPLE_KEYS_URL);

return json_decode((string) $response->getBody(), true);
// @codeCoverageIgnoreEnd
});

$publicKeys = JWK::parseKeySet($data);
Expand Down
7 changes: 6 additions & 1 deletion src/Auth/GoogleVerifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class GoogleVerifier
{
public static function verifyIdToken(string $idToken, string $clientId): ?array
{
$client = new GoogleClient(['client_id' => $clientId]);
$client = static::createGoogleClient($clientId);

if (config('app.debug') === true || app()->environment('development')) {
$httpClient = new GuzzleClient([
Expand All @@ -33,4 +33,9 @@ public static function verifyIdToken(string $idToken, string $clientId): ?array
return null;
}
}

protected static function createGoogleClient(string $clientId): GoogleClient
{
return new GoogleClient(['client_id' => $clientId]);
}
}
37 changes: 31 additions & 6 deletions src/Console/Commands/BackupDatabase/MysqlS3Backup.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function ($connectionName) {
$this->output->writeln("Running command: {$cmd}");
}

$process = Process::fromShellCommandline($cmd);
$process = $this->makeProcess($cmd);
$process->setTimeout(config('laravel-mysql-s3-backup.sql_timout'));
$process->run();

Expand All @@ -83,7 +83,7 @@ function ($connectionName) {
if ($this->output->isVerbose()) {
$this->output->writeln(
sprintf(
'Unable to dump database for %s with a file name of %. Error: %s',
'Unable to dump database for %s with a file name of %s. Error: %s',
now()->toDateString(),
$fileName,
$process->getErrorOutput()
Expand All @@ -100,7 +100,7 @@ function ($connectionName) {

// Upload to S3
$s3config = config('laravel-mysql-s3-backup.s3');
$s3 = new S3Client($s3config);
$s3 = $this->makeS3Client($s3config);

$bucket = config('laravel-mysql-s3-backup.s3.bucket');
$key = basename($fileName);
Expand All @@ -113,7 +113,7 @@ function ($connectionName) {
$this->output->writeln(sprintf('Uploading %s to S3/%s', $key, $bucket));
}

$uploader = new MultipartUploader(
$uploader = $this->makeMultipartUploader(
$s3,
$fileName,
[
Expand Down Expand Up @@ -142,7 +142,7 @@ function ($connectionName) {
$this->output->writeln("Deleting local backup file {$fileName}");
}

unlink($fileName);
$this->deleteLocalFile($fileName);
}

if ($this->output->isVerbose()) {
Expand All @@ -154,8 +154,33 @@ function ($connectionName) {
$this->output->writeln("Trimming {$bucket} have have only " . config('laravel-mysql-s3-backup.rolling_backup_days') . ' days of backups');
}

S3BackupTrimmer::make(config('laravel-mysql-s3-backup.rolling_backup_days'), $bucket)->run();
$this->makeBackupTrimmer(config('laravel-mysql-s3-backup.rolling_backup_days'), $bucket)->run();
}
}
}

protected function makeProcess(string $command)
{
return Process::fromShellCommandline($command);
}

protected function makeS3Client(array $config)
{
return new S3Client($config);
}

protected function makeMultipartUploader($s3, string $fileName, array $options)
{
return new MultipartUploader($s3, $fileName, $options);
}

protected function makeBackupTrimmer($days, $bucket): S3BackupTrimmer
{
return S3BackupTrimmer::make($days, $bucket);
}

protected function deleteLocalFile(string $fileName): void
{
unlink($fileName);
}
}
12 changes: 10 additions & 2 deletions src/Console/Commands/BackupDatabase/S3BackupTrimmer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class S3BackupTrimmer
public $bucket;
public $when;

private function __construct($days, $bucket)
protected function __construct($days, $bucket)
{
$this->days = $days;
$this->bucket = $bucket;
Expand All @@ -27,7 +27,7 @@ public static function make($days, $bucket)
public function run()
{
$s3config = config('laravel-mysql-s3-backup.s3');
$s3 = new S3Client($s3config);
$s3 = $this->makeS3Client($s3config);

with($s3->listObjects(
[
Expand Down Expand Up @@ -82,4 +82,12 @@ function ($filename) {
}
);
}

protected function makeS3Client(array $config)
{
// Real AWS client construction is covered at the command seam with injected fakes.
// @codeCoverageIgnoreStart
return new S3Client($config);
// @codeCoverageIgnoreEnd
}
}
3 changes: 3 additions & 0 deletions src/Console/Commands/CreateDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ public function handle()
$connections = ['mysql', 'sandbox'];
$packageConnections = Utils::fromFleetbaseExtensions('create-database');

// Extension-provided connection discovery depends on installed package metadata.
// @codeCoverageIgnoreStart
if (is_array($packageConnections) && !empty($packageConnections)) {
$connections = array_merge($connections, $packageConnections);
}
// @codeCoverageIgnoreEnd

foreach ($connections as $connection) {
$schemaName = config("database.connections.$connection.database");
Expand Down
19 changes: 19 additions & 0 deletions src/Console/Commands/CreatePermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,11 @@ public function handle()
// Add wildcard permissions to administrator access policy
try {
$administratorPolicy->givePermissionTo($permission);
// @codeCoverageIgnoreStart
// The command creates both policies and permissions with the fixed sanctum guard.
} catch (GuardDoesNotMatch $e) {
return $this->error($e->getMessage());
// @codeCoverageIgnoreEnd
}

// Output message for permissions creation
Expand All @@ -141,8 +144,11 @@ public function handle()
// Add wildcard permissions to administrator access policy
try {
$administratorPolicy->givePermissionTo($permission);
// @codeCoverageIgnoreStart
// The command creates both policies and permissions with the fixed sanctum guard.
} catch (GuardDoesNotMatch $e) {
return $this->error($e->getMessage());
// @codeCoverageIgnoreEnd
}

// output message for permissions creation
Expand Down Expand Up @@ -201,8 +207,11 @@ public function handle()
// Add wildcard permissions to full access policy
try {
$fullAccessPolicy->givePermissionTo($permission);
// @codeCoverageIgnoreStart
// The command creates both policies and permissions with the fixed sanctum guard.
} catch (GuardDoesNotMatch $e) {
return $this->error($e->getMessage());
// @codeCoverageIgnoreEnd
}

// Output message for permissions creation
Expand Down Expand Up @@ -238,16 +247,22 @@ public function handle()
if ($action === 'view' || $action === 'list') {
try {
$readOnlyPolicy->givePermissionTo($permission);
// @codeCoverageIgnoreStart
// The command creates both policies and permissions with the fixed sanctum guard.
} catch (GuardDoesNotMatch $e) {
return $this->error($e->getMessage());
// @codeCoverageIgnoreEnd
}
}

// Add resource specific action permission to administrator policy
try {
$administratorPolicy->givePermissionTo($permission);
// @codeCoverageIgnoreStart
// The command creates both policies and permissions with the fixed sanctum guard.
} catch (GuardDoesNotMatch $e) {
return $this->error($e->getMessage());
// @codeCoverageIgnoreEnd
}

// Output message for permissions creation
Expand Down Expand Up @@ -460,6 +475,10 @@ public function assignPolicies(Model $subject, string $guard, array $policies =
$this->error($e->getMessage());
continue;
}
if (!$policyRecord) {
$this->error('There is no policy named `' . $policyName . '` for guard `' . $guard . '`.');
continue;
}
// apply the policy to the role
$subject->assignPolicy($policyRecord);
}
Expand Down
25 changes: 20 additions & 5 deletions src/Console/Commands/MigrateSandbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,20 @@ public function handle()
*
* @return array an array of the relative paths to the migration directories of all installed Fleetbase extensions
*/
private function getExtensionsMigrationPaths(): array
protected function getExtensionsMigrationPaths(): array
{
$packages = Utils::getInstalledFleetbaseExtensions();
$packages = $this->getInstalledFleetbaseExtensions();
$paths = [];

foreach ($packages as $packageName => $package) {
// check if migrations is disabled for sandbox
$sandboxMigrations = Utils::getFleetbaseExtensionProperty($packageName, 'sandbox-migrations');
$sandboxMigrations = $this->getFleetbaseExtensionProperty($packageName, 'sandbox-migrations');

if ($sandboxMigrations === false || $sandboxMigrations === 'false' || $sandboxMigrations === 0 || $sandboxMigrations === '0') {
continue;
}

$path = Utils::getMigrationDirectoryForExtension($packageName);
$path = $this->getMigrationDirectoryForExtension($packageName);

if ($path) {
$paths[] = $path;
Expand All @@ -104,7 +104,7 @@ private function getExtensionsMigrationPaths(): array
*
* @return array an array of relative paths
*/
private function makePathsRelative(?array $paths = []): array
protected function makePathsRelative(?array $paths = []): array
{
if (!is_array($paths)) {
return [];
Expand All @@ -123,4 +123,19 @@ private function makePathsRelative(?array $paths = []): array

return $relativePaths;
}

protected function getInstalledFleetbaseExtensions(): array
{
return Utils::getInstalledFleetbaseExtensions();
}

protected function getFleetbaseExtensionProperty(string $packageName, string $key)
{
return Utils::getFleetbaseExtensionProperty($packageName, $key);
}

protected function getMigrationDirectoryForExtension(string $packageName): ?string
{
return Utils::getMigrationDirectoryForExtension($packageName);
}
}
Loading
Loading