tag containing the id and checks for * the `checked` attribute anywhere inside — the partial spreads the * attributes across multiple lines and the blade `@checked` directive * emits a bare `checked` keyword rather than `checked="checked"`, so a * simple substring assertion would be too loose or too tight depending * on formatting. */ private function assertRadioChecked(string $html, string $id, bool $expected, string $context): void { $pattern = '/]*\bid="'.preg_quote($id, '/').'"[^>]*>/is'; $found = preg_match($pattern, $html, $matches); $this->assertSame(1, $found, "Could not find in {$context}"); $isChecked = preg_match('/\bchecked\b/i', $matches[0]) === 1; $expected ? $this->assertTrue($isChecked, "{$id} should be checked in {$context}") : $this->assertFalse($isChecked, "{$id} should NOT be checked in {$context}"); } // ------------------------------------------------------------------- // Groups edit page (use_inherit = false — only allow/deny rendered). // ------------------------------------------------------------------- public function test_group_edit_pre_checks_deny_when_reports_is_denied() { $group = Group::factory()->create([ 'permissions' => json_encode(['reports.view' => '-1']), ]); $html = $this->actingAs(User::factory()->superuser()->create()) ->get(route('groups.edit', $group)) ->assertOk() ->getContent(); $this->assertRadioChecked($html, 'reports_deny', true, 'group edit with reports.view = -1'); $this->assertRadioChecked($html, 'reports_allow', false, 'group edit with reports.view = -1'); } public function test_group_edit_pre_checks_allow_when_reports_is_allowed() { $group = Group::factory()->create([ 'permissions' => json_encode(['reports.view' => '1']), ]); $html = $this->actingAs(User::factory()->superuser()->create()) ->get(route('groups.edit', $group)) ->assertOk() ->getContent(); $this->assertRadioChecked($html, 'reports_allow', true, 'group edit with reports.view = 1'); $this->assertRadioChecked($html, 'reports_deny', false, 'group edit with reports.view = 1'); } // ------------------------------------------------------------------- // Users edit page (use_inherit = true — all three radios rendered). // ------------------------------------------------------------------- public function test_user_edit_pre_checks_deny_when_reports_is_denied() { $target = User::factory()->create([ 'permissions' => json_encode(['reports.view' => '-1']), ]); $html = $this->actingAs(User::factory()->superuser()->create()) ->get(route('users.edit', $target)) ->assertOk() ->getContent(); $this->assertRadioChecked($html, 'reports_deny', true, 'user edit with reports.view = -1'); $this->assertRadioChecked($html, 'reports_allow', false, 'user edit with reports.view = -1'); $this->assertRadioChecked($html, 'reports_inherit', false, 'user edit with reports.view = -1'); } public function test_user_edit_pre_checks_allow_when_reports_is_allowed() { $target = User::factory()->create([ 'permissions' => json_encode(['reports.view' => '1']), ]); $html = $this->actingAs(User::factory()->superuser()->create()) ->get(route('users.edit', $target)) ->assertOk() ->getContent(); $this->assertRadioChecked($html, 'reports_allow', true, 'user edit with reports.view = 1'); $this->assertRadioChecked($html, 'reports_deny', false, 'user edit with reports.view = 1'); $this->assertRadioChecked($html, 'reports_inherit', false, 'user edit with reports.view = 1'); } public function test_user_edit_pre_checks_inherit_when_reports_is_unset() { // No reports.view key at all — inherit should be the fallback. $target = User::factory()->create([ 'permissions' => json_encode([]), ]); $html = $this->actingAs(User::factory()->superuser()->create()) ->get(route('users.edit', $target)) ->assertOk() ->getContent(); $this->assertRadioChecked($html, 'reports_inherit', true, 'user edit with no reports permission set'); $this->assertRadioChecked($html, 'reports_allow', false, 'user edit with no reports permission set'); $this->assertRadioChecked($html, 'reports_deny', false, 'user edit with no reports permission set'); } }