$abilities name, isDirect, readonly */ private function integration(string $id, array $abilities, bool $available = true): Integration { $mocks = []; foreach ($abilities as [$name, $direct, $readonly]) { $ability = Mockery::mock(Ability::class); $ability->allows('name')->andReturn($name); $ability->allows('label')->andReturn('Label ' . $name); $ability->allows('isDirect')->andReturn($direct); $ability->allows('annotations')->andReturn(['readonly' => $readonly]); $mocks[] = $ability; } $integration = Mockery::mock(Integration::class); $integration->allows('id')->andReturn($id); $integration->allows('isAvailable')->andReturn($available); $integration->allows('abilities')->andReturn($mocks); return $integration; } private function registry(): IntegrationRegistry { return new IntegrationRegistry( $this->integration('core', [['lit/guide', true, true], ['lit/site-status', true, true]]), $this->integration('media', [['lit/media-preview', true, true], ['lit/media-upload', false, false]]), $this->integration('divi', [['lit/divi-outline', true, true], ['lit/divi-update', true, false]]), $this->integration('pods', [['lit/pods-x', true, true]], false) ); } /** @param array $option */ private function render(array $option, ?IntegrationRegistry $registry = null): string { Functions\stubEscapeFunctions(); Functions\stubTranslationFunctions(); Functions\when('settings_fields')->justReturn(null); Functions\when('submit_button')->justReturn(null); Functions\when('selected')->alias( static fn ($a, $b = true, $echo = true): string => (string) $a === (string) $b ? ' selected="selected"' : '' ); Functions\when('checked')->alias( static fn ($a, $b = true, $echo = true): string => (string) $a === (string) $b ? ' checked="checked"' : '' ); ob_start(); (new ToolsTab($registry ?? $this->registry(), new ExposurePolicy($option)))->render(); return (string) ob_get_clean(); } private function select(string $html, string $key): string { $start = strpos($html, '', $update ); $outline = $this->row($html, 'lit/divi-outline'); self::assertStringNotContainsString('disabled>', $outline); self::assertStringNotContainsString('nur lesen', $outline); } public function testCountsDirectToolsUnderTheSavedSettings(): void { $html = $this->render(['@group:divi' => 'disabled']); // guide, site-status, media-preview (divi disabled, media-upload indirect by default). self::assertStringContainsString('Direkt sichtbar: 3 Tools', $html); self::assertStringNotContainsString('Kontext', $html); self::assertLessThan(strpos($html, 'integration('wordpress', $many)); $warned = $this->render([], $registry); $notWarned = $this->render(['lit/tool-1' => 'indirect'], $registry); self::assertStringContainsString('Direkt sichtbar: 26 Tools', $warned); self::assertStringContainsString('Kontext', $warned); self::assertStringContainsString('WordPress (26 Tools)', $warned); self::assertStringContainsString('Direkt sichtbar: 25 Tools', $notWarned); self::assertStringNotContainsString('Kontext', $notWarned); } public function testUnknownGroupsUseTheirIdAndEverythingIsEscaped(): void { $registry = new IntegrationRegistry($this->integration('shop', [['lit/shop-', true, true]])); $html = $this->render([], $registry); self::assertStringContainsString('shop (1 Tool)', $html); self::assertStringNotContainsString('', $html); self::assertStringContainsString('lit/shop-<b>', $html); } }