Willkommen

Leistungen

' . '

Seit 1987 in Köln.

' . 'TeamMehr'; public function testSummarizesHtml(): void { $summary = RenderSummary::fromHtml(self::HTML); self::assertSame([['level' => 1, 'text' => 'Willkommen'], ['level' => 3, 'text' => 'Leistungen']], $summary['headings']); self::assertSame(['Seit 1987 in Köln.', 'Beratung'], $summary['texts']); self::assertSame(['text' => 'in Köln', 'href' => '/kontakt'], $summary['links'][0]); self::assertSame( [['src' => 'https://k.test/a.jpg', 'alt' => 'Team'], ['src' => 'https://k.test/b.jpg', 'alt' => null]], $summary['images'] ); self::assertSame( [ 'Sprung in der Überschriftenhierarchie: h1 → h3 ("Leistungen").', 'Bild ohne Alt-Text: https://k.test/b.jpg', 'Link ohne Ziel: "Mehr".', ], $summary['warnings'] ); self::assertSame([], RenderSummary::fromHtml('')['headings']); self::assertCount(2, RenderSummary::fromHtml(str_repeat('

x

', 5), 2)['texts']); } public function testTruncatesLongExtractedStrings(): void { $longHeading = str_repeat('Ü', 250); $longText = str_repeat('a', 400); $longLinkText = str_repeat('b', 200); $longHref = 'https://k.test/' . str_repeat('c', 400); $longAlt = str_repeat('d', 300); $html = "

{$longHeading}

{$longText}

" . "{$longLinkText}" . "\"{$longAlt}\""; $summary = RenderSummary::fromHtml($html); self::assertSame(200, mb_strlen($summary['headings'][0]['text'])); self::assertStringEndsWith('…', $summary['headings'][0]['text']); self::assertSame(300, mb_strlen($summary['texts'][0])); self::assertStringEndsWith('…', $summary['texts'][0]); self::assertSame(150, mb_strlen($summary['links'][0]['text'])); self::assertStringEndsWith('…', $summary['links'][0]['text']); self::assertSame(300, mb_strlen($summary['links'][0]['href'])); self::assertStringEndsWith('…', $summary['links'][0]['href']); self::assertSame(200, mb_strlen($summary['images'][0]['alt'])); self::assertStringEndsWith('…', $summary['images'][0]['alt']); } public function testRepresentsDataUrisAsAShortMarkerInsteadOfTruncatingThem(): void { $dataUri = 'data:image/png;base64,' . base64_encode(str_repeat('x', 5000)); $html = 'Anhang'; $summary = RenderSummary::fromHtml($html); $marker = 'data:image/png;… (' . strlen($dataUri) . ' Bytes)'; self::assertSame($marker, $summary['images'][0]['src']); self::assertSame($marker, $summary['links'][0]['href']); } public function testPrefersDataSrcOrDataLazySrcOverAPlaceholderSrc(): void { $html = 'Team' . ''; $summary = RenderSummary::fromHtml($html); self::assertSame('https://k.test/real.jpg', $summary['images'][0]['src']); self::assertSame('https://k.test/lazy.jpg', $summary['images'][1]['src']); } public function testWarnsAboutMultipleH1Headings(): void { $summary = RenderSummary::fromHtml('

Erste

Zweite

'); self::assertContains('2 Überschriften der Ebene h1 im Inhalt.', $summary['warnings']); } public function testDoesNotDuplicateTextFromNestedParagraphsListItemsOrBlockquotes(): void { $html = '' . '
Zitat
innen
'; $summary = RenderSummary::fromHtml($html); self::assertSame(['Punkt eingebettet', 'Zitat innen'], $summary['texts']); } public function testIgnoresScriptStyleAndNoscriptText(): void { $html = '

Sichtbar' . ' Ende

'; $summary = RenderSummary::fromHtml($html); self::assertSame(['Sichtbar Ende'], $summary['texts']); } public function testRendersTheEntryAndAddsNotes(): void { $post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_password' => 'geheim']); Functions\when('get_post')->justReturn($post); Functions\when('current_user_can')->justReturn(true); Functions\when('get_permalink')->justReturn('https://k.test/start/'); $schema = SchemaFixture::managed(); $renderer = Mockery::mock(PageRenderer::class); $renderer->expects('render')->with($post)->andReturn(self::HTML); $ability = new PageRenderSummaryAbility($schema, $renderer); self::assertTrue($ability->permission(['post_id' => 7])); $result = $ability->execute(['post_id' => 7]); self::assertSame(7, $result['post_id']); self::assertSame('https://k.test/start/', $result['url']); self::assertCount(2, $result['headings']); self::assertCount(3, $result['notes']); self::assertTrue($ability->isDirect()); self::assertTrue($ability->annotations()['readonly']); } public function testNotesEveryGlobalModuleTheSummaryCannotShow(): void { $content = DiviFixtures::markup('stage3/page--globale-instanzen.html'); $post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_status' => 'draft', 'post_content' => $content]); Functions\when('get_post')->justReturn($post); Functions\when('current_user_can')->justReturn(true); Functions\when('get_permalink')->justReturn('https://kunde.test/?page_id=7'); $renderer = Mockery::mock(PageRenderer::class); $renderer->allows('render')->andReturn('

Text

'); $ability = new PageRenderSummaryAbility(SchemaFixture::managed(), $renderer); $notes = $ability->execute(['post_id' => 7])['notes']; $globals = array_values(array_filter($notes, static fn (string $note): bool => str_starts_with($note, 'Globales Modul'))); self::assertCount(2, $globals); self::assertStringContainsString('Globales Modul 1058 ist im Auszug nicht enthalten', $globals[0]); self::assertStringContainsString('lit-divi-outline mit post_id 1059', $globals[1]); } /** Ruling P13: without library access the note counts global modules instead of naming them. */ public function testWithoutLibraryAccessGlobalModulesAreOnlyCounted(): void { $content = DiviFixtures::markup('stage3/page--globale-instanzen.html'); $post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_status' => 'draft', 'post_content' => $content]); Functions\when('get_post')->justReturn($post); Functions\when('current_user_can')->justReturn(true); Functions\when('get_permalink')->justReturn('https://kunde.test/?page_id=7'); $renderer = Mockery::mock(PageRenderer::class); $renderer->allows('render')->andReturn('

Text

'); $ability = new PageRenderSummaryAbility(SchemaFixture::managed(), $renderer, static fn (): bool => false); $result = $ability->execute(['post_id' => 7]); $joined = implode("\n", $result['notes']); self::assertStringContainsString('2 globale Module sind im Auszug nicht enthalten', $joined); self::assertStringNotContainsString('1058', $joined); self::assertStringNotContainsString('1059', $joined); self::assertStringNotContainsString('1058', (string) json_encode($result)); } /** Ruling P13: with library access the notes name each entry. */ public function testWithLibraryAccessGlobalModulesAreNamed(): void { $content = DiviFixtures::markup('stage3/page--globale-instanzen.html'); $post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_status' => 'draft', 'post_content' => $content]); Functions\when('get_post')->justReturn($post); Functions\when('current_user_can')->justReturn(true); Functions\when('get_permalink')->justReturn('https://kunde.test/?page_id=7'); $renderer = Mockery::mock(PageRenderer::class); $renderer->allows('render')->andReturn('

Text

'); $ability = new PageRenderSummaryAbility(SchemaFixture::managed(), $renderer, static fn (): bool => true); $joined = implode("\n", $ability->execute(['post_id' => 7])['notes']); self::assertStringContainsString('Globales Modul 1058', $joined); } public function testLibraryEntriesAreNoManagedContent(): void { Functions\when('get_post')->justReturn(new WP_Post(['ID' => 1058, 'post_type' => 'et_pb_layout'])); $schema = Mockery::mock(ContentSchema::class); $schema->allows('isManaged')->with('et_pb_layout')->andReturn(false); $ability = new PageRenderSummaryAbility($schema, Mockery::mock(PageRenderer::class)); self::assertToolError($ability->permission(['post_id' => 1058]), 'not_found'); } }