-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathGetStatusActionTest.php
More file actions
128 lines (106 loc) · 4.81 KB
/
Copy pathGetStatusActionTest.php
File metadata and controls
128 lines (106 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
/*
* Copyright (c) 2025-2026 Netresearch DTT GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Tests\Controller;
use Tests\AbstractWebTestCase;
use Tests\Traits\HttpRequestTestTrait;
use function sprintf;
use const JSON_THROW_ON_ERROR;
use const PHP_VERSION;
/**
* @internal
*
* @coversNothing
*/
final class GetStatusActionTest extends AbstractWebTestCase
{
use HttpRequestTestTrait;
public function testReturnsDiagnosticsForAdmin(): void
{
// AbstractWebTestCase logs in as 'unittest', whose type is ADMIN.
$this->getJson('/admin/status');
$this->assertStatusCode(200);
$json = $this->getJsonResponse($this->client->getResponse());
foreach (['app', 'build', 'php', 'symfony', 'packages', 'database', 'subsystems', 'config'] as $section) {
self::assertArrayHasKey($section, $json);
}
self::assertIsArray($json['php']);
self::assertIsArray($json['database']);
self::assertSame(PHP_VERSION, $json['php']['version']);
self::assertArrayHasKey('platform', $json['database']);
// Build provenance: the GitHub links are always present; the commit/ref
// are null in the test env (no APP_BUILD_* baked in) → no fabricated link.
self::assertIsArray($json['build']);
self::assertSame('https://github.com/netresearch/timetracker', $json['build']['repositoryUrl']);
self::assertSame('https://github.com/netresearch/timetracker/releases', $json['build']['releasesUrl']);
self::assertNull($json['build']['revision']);
self::assertNull($json['build']['commitUrl']);
// Never leaks credentials: no password anywhere, no DB user key.
self::assertStringNotContainsStringIgnoringCase('password', (string) json_encode($json));
self::assertArrayNotHasKey('user', $json['database']);
}
public function testSubsystemCardsCoverExpectedStorage(): void
{
$this->getJson('/admin/status');
$this->assertStatusCode(200);
$json = $this->getJsonResponse($this->client->getResponse());
self::assertIsArray($json['subsystems']);
$byId = [];
foreach ($json['subsystems'] as $card) {
self::assertIsArray($card);
foreach (['id', 'backend', 'status', 'config', 'adr'] as $key) {
self::assertArrayHasKey($key, $card);
}
$id = $card['id'];
self::assertIsString($id);
$byId[$id] = $card;
}
// Every storage/subsystem the page promises is present.
foreach (['database', 'sessions', 'cache', 'api_tokens', 'passkeys_mfa', 'authentication', 'api', 'mcp', 'jira'] as $id) {
self::assertArrayHasKey($id, $byId, sprintf('missing subsystem card: %s', $id));
}
// The token card reports live counts and the recognizable prefix.
$apiTokenConfig = $byId['api_tokens']['config'];
self::assertIsArray($apiTokenConfig);
self::assertIsInt($apiTokenConfig['active']);
self::assertSame('tt_pat_', $apiTokenConfig['prefix']);
// Sessions are file-based and link ADR-019 — a regression guard against
// silently reporting a shared backend that is not actually deployed.
self::assertSame('ADR-019', $byId['sessions']['adr']);
$sessionsBackend = $byId['sessions']['backend'];
self::assertIsString($sessionsBackend);
self::assertStringContainsStringIgnoringCase('file', $sessionsBackend);
// The richer payload still leaks no credentials.
self::assertStringNotContainsStringIgnoringCase('password', json_encode($json, JSON_THROW_ON_ERROR));
}
public function testVersionPrefersTheBuildRefTag(): void
{
// The profiling image is built only on tag pushes, so a deployed release
// carries its tag in APP_BUILD_REF. The "Application → Version" field
// surfaces it (stripped of the leading "v") rather than Composer's
// unversioned root default ("1.0.0+no-version-set").
putenv('APP_BUILD_REF=v9.9.9');
$_SERVER['APP_BUILD_REF'] = 'v9.9.9';
try {
$this->getJson('/admin/status');
$this->assertStatusCode(200);
$json = $this->getJsonResponse($this->client->getResponse());
self::assertIsArray($json['app']);
self::assertSame('9.9.9', $json['app']['version']);
self::assertIsArray($json['build']);
self::assertSame('v9.9.9', $json['build']['ref']);
} finally {
putenv('APP_BUILD_REF');
unset($_SERVER['APP_BUILD_REF']);
}
}
public function testForbiddenForNonAdmin(): void
{
$this->logInSession('developer'); // type DEV — not an admin
$this->getJson('/admin/status');
$this->assertStatusCode(403);
}
}