release: v3.1.0 premium smart core engines and 14 new accessibility rules

This commit is contained in:
Enes Yakıştır
2026-07-13 10:54:25 +03:00
parent 7f3bf3cb7d
commit 5292c2c865
67 changed files with 2639 additions and 29 deletions
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\AriaLabelledbyExists;
class AriaLabelledbyExistsTest extends TestCase
{
public function testFlagsMissingAriaLabelTarget(): void
{
$scanner = new Scanner();
$scanner->addRule(new AriaLabelledbyExists());
$violations = $scanner->scan('<div><button aria-labelledby="non_existent_id">Submit</button></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_4_1_2_ARIA_LABELLEDBY', $violations[0]->ruleId);
}
public function testPassesExistingAriaLabelTarget(): void
{
$scanner = new Scanner();
$scanner->addRule(new AriaLabelledbyExists());
$violations = $scanner->scan('<div><div id="real_id">Label</div><button aria-labelledby="real_id">Submit</button></div>');
$this->assertCount(0, $violations);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\AutocompleteValid;
class AutocompleteValidTest extends TestCase
{
public function testFlagsMissingAutocomplete(): void
{
$scanner = new Scanner();
$scanner->addRule(new AutocompleteValid());
$violations = $scanner->scan('<div><input type="email" name="user_email" /></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_3_5_AUTOCOMPLETE', $violations[0]->ruleId);
}
public function testPassesWithAutocomplete(): void
{
$scanner = new Scanner();
$scanner->addRule(new AutocompleteValid());
$violations = $scanner->scan('<div><input type="email" name="user_email" autocomplete="email" /></div>');
$this->assertCount(0, $violations);
}
public function testSkipsNonPersonalInputs(): void
{
$scanner = new Scanner();
$scanner->addRule(new AutocompleteValid());
$violations = $scanner->scan('<div><input type="checkbox" name="agree" /><input type="submit" /></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\AutofocusBanned;
class AutofocusBannedTest extends TestCase
{
public function testFlagsAutofocusAttribute(): void
{
$scanner = new Scanner();
$scanner->addRule(new AutofocusBanned());
$violations = $scanner->scan('<div><input type="text" name="search" autofocus /></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_2_4_3_AUTOFOCUS', $violations[0]->ruleId);
}
public function testPassesNormalInput(): void
{
$scanner = new Scanner();
$scanner->addRule(new AutofocusBanned());
$violations = $scanner->scan('<div><input type="text" name="search" /></div>');
$this->assertCount(0, $violations);
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\BannedSelectors;
class BannedSelectorsTest extends TestCase
{
public function testFlagsBannedCssSelectorTags(): void
{
$scanner = new Scanner();
$scanner->addRule(new BannedSelectors());
$violations = $scanner->scan('<div><center>Obsolete tag</center><div align="center">Deprecated align</div></div>');
$this->assertCount(2, $violations);
$ruleIds = array_map(fn($v) => $v->ruleId, $violations);
$this->assertContains('BannedSelectors', $ruleIds);
}
public function testPassesSemanticHtml(): void
{
$scanner = new Scanner();
$scanner->addRule(new BannedSelectors());
$violations = $scanner->scan('<div><span style="text-align: center;">Semantic structure</span></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\BlinkTagBanned;
class BlinkTagBannedTest extends TestCase
{
public function testFlagsBlinkTag(): void
{
$scanner = new Scanner();
$scanner->addRule(new BlinkTagBanned());
$violations = $scanner->scan('<div><blink>Blinking text!</blink></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_2_2_2_BLINK', $violations[0]->ruleId);
}
public function testPassesNormalSpan(): void
{
$scanner = new Scanner();
$scanner->addRule(new BlinkTagBanned());
$violations = $scanner->scan('<div><span>Normal text</span></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\DuplicateH1;
class DuplicateH1Test extends TestCase
{
public function testFlagsDuplicateH1(): void
{
$scanner = new Scanner();
$scanner->addRule(new DuplicateH1());
$violations = $scanner->scan('<div><h1>Heading 1</h1><h1>Heading 2</h1></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_3_1_DUPLICATE_H1', $violations[0]->ruleId);
}
public function testPassesSingleH1(): void
{
$scanner = new Scanner();
$scanner->addRule(new DuplicateH1());
$violations = $scanner->scan('<div><h1>Heading 1</h1><h2>Heading 2</h2></div>');
$this->assertCount(0, $violations);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\FormSubmitButton;
class FormSubmitButtonTest extends TestCase
{
public function testFlagsFormWithoutSubmitButton(): void
{
$scanner = new Scanner();
$scanner->addRule(new FormSubmitButton());
$violations = $scanner->scan('<form><input type="text" name="name" /></form>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_3_2_2_FORM_SUBMIT', $violations[0]->ruleId);
}
public function testPassesFormWithButtonSubmit(): void
{
$scanner = new Scanner();
$scanner->addRule(new FormSubmitButton());
$violations = $scanner->scan('<form><input type="text" name="name" /><button>Submit</button></form>');
$this->assertCount(0, $violations);
}
public function testPassesFormWithInputSubmit(): void
{
$scanner = new Scanner();
$scanner->addRule(new FormSubmitButton());
$violations = $scanner->scan('<form><input type="text" name="name" /><input type="submit" value="Go" /></form>');
$this->assertCount(0, $violations);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\ImageAltLong;
class ImageAltLongTest extends TestCase
{
public function testFlagsTooLongAltText(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltLong());
$longAlt = str_repeat("a", 151);
$violations = $scanner->scan('<div><img src="pic.png" alt="' . $longAlt . '" /></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_1_1_ALT_LONG', $violations[0]->ruleId);
}
public function testPassesNormalAltText(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltLong());
$violations = $scanner->scan('<div><img src="pic.png" alt="Short description" /></div>');
$this->assertCount(0, $violations);
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\ImageAltPlaceholder;
class ImageAltPlaceholderTest extends TestCase
{
public function testFlagsPlaceholderAltText(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltPlaceholder());
$violations = $scanner->scan('<div><img src="logo.png" alt="logo" /></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_1_1_ALT_PLACEHOLDER', $violations[0]->ruleId);
}
public function testFlagsFilenameAltText(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltPlaceholder());
$violations = $scanner->scan('<div><img src="banner.jpg" alt="header_banner.jpg" /></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_1_1_ALT_PLACEHOLDER', $violations[0]->ruleId);
}
public function testPassesDescriptiveAltText(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltPlaceholder());
$violations = $scanner->scan('<div><img src="banner.jpg" alt="YakNet Static Analysis Console Banner Image" /></div>');
$this->assertCount(0, $violations);
}
public function testPassesEmptyAlt(): void
{
$scanner = new Scanner();
$scanner->addRule(new ImageAltPlaceholder());
$violations = $scanner->scan('<div><img src="decoration.jpg" alt="" /></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\LinkTextUrl;
class LinkTextUrlTest extends TestCase
{
public function testFlagsLinkWithRawUrlText(): void
{
$scanner = new Scanner();
$scanner->addRule(new LinkTextUrl());
$violations = $scanner->scan('<div><a href="https://google.com">https://google.com</a></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_2_4_4_LINK_URL', $violations[0]->ruleId);
}
public function testPassesDescriptiveLinkText(): void
{
$scanner = new Scanner();
$scanner->addRule(new LinkTextUrl());
$violations = $scanner->scan('<div><a href="https://google.com">Google Search Engine</a></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\ListStructure;
class ListStructureTest extends TestCase
{
public function testFlagsInvalidDirectChildrenInList(): void
{
$scanner = new Scanner();
$scanner->addRule(new ListStructure());
$violations = $scanner->scan('<ul><div>Invalid</div><li>Valid</li></ul>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_3_1_LIST_STRUCTURE', $violations[0]->ruleId);
}
public function testPassesValidListStructure(): void
{
$scanner = new Scanner();
$scanner->addRule(new ListStructure());
$violations = $scanner->scan('<ul><li>Valid 1</li><li>Valid 2</li><script>alert(1);</script></ul>');
$this->assertCount(0, $violations);
}
}
@@ -0,0 +1,30 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\PresentationTagsBanned;
class PresentationTagsBannedTest extends TestCase
{
public function testFlagsBannedPresentationTags(): void
{
$scanner = new Scanner();
$scanner->addRule(new PresentationTagsBanned());
$violations = $scanner->scan('<div><center>Centered text</center><strike>Strikethrough</strike></div>');
$this->assertCount(2, $violations);
$this->assertSame('WCAG_1_3_1_PRESENTATION_TAGS', $violations[0]->ruleId);
$this->assertSame('WCAG_1_3_1_PRESENTATION_TAGS', $violations[1]->ruleId);
}
public function testPassesCssStyling(): void
{
$scanner = new Scanner();
$scanner->addRule(new PresentationTagsBanned());
$violations = $scanner->scan('<div><span style="text-align: center; text-decoration: line-through;">Styled Text</span></div>');
$this->assertCount(0, $violations);
}
}
@@ -0,0 +1,38 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\ScrollableRegionFocusable;
class ScrollableRegionFocusableTest extends TestCase
{
public function testFlagsScrollableRegionWithoutTabindex(): void
{
$scanner = new Scanner();
$scanner->addRule(new ScrollableRegionFocusable());
$violations = $scanner->scan('<div style="overflow: scroll; height: 100px;">Scrollable content</div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_2_1_1_SCROLLABLE_FOCUS', $violations[0]->ruleId);
}
public function testPassesScrollableRegionWithTabindex(): void
{
$scanner = new Scanner();
$scanner->addRule(new ScrollableRegionFocusable());
$violations = $scanner->scan('<div style="overflow-y: auto;" tabindex="0">Scrollable content</div>');
$this->assertCount(0, $violations);
}
public function testPassesNonScrollableElement(): void
{
$scanner = new Scanner();
$scanner->addRule(new ScrollableRegionFocusable());
$violations = $scanner->scan('<div style="color: blue;">Non-scrollable content</div>');
$this->assertCount(0, $violations);
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\SvgAltText;
class SvgAltTextTest extends TestCase
{
public function testFlagsSvgWithoutAlt(): void
{
$scanner = new Scanner();
$scanner->addRule(new SvgAltText());
$violations = $scanner->scan('<div><svg width="10"><circle /></svg></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_1_1_SVG', $violations[0]->ruleId);
}
public function testPassesSvgWithAriaLabel(): void
{
$scanner = new Scanner();
$scanner->addRule(new SvgAltText());
$violations = $scanner->scan('<div><svg width="10" aria-label="Company logo"><circle /></svg></div>');
$this->assertCount(0, $violations);
}
public function testPassesSvgWithTitle(): void
{
$scanner = new Scanner();
$scanner->addRule(new SvgAltText());
$violations = $scanner->scan('<div><svg width="10"><title>Real Title</title><circle /></svg></div>');
$this->assertCount(0, $violations);
}
public function testPassesSvgHidden(): void
{
$scanner = new Scanner();
$scanner->addRule(new SvgAltText());
$violations = $scanner->scan('<div><svg width="10" aria-hidden="true"><circle /></svg></div>');
$this->assertCount(0, $violations);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace YakNet\AccessibilityConsole\Tests\Rules;
use PHPUnit\Framework\TestCase;
use YakNet\AccessibilityConsole\Core\Scanner;
use YakNet\AccessibilityConsole\Rules\TableSummaryBanned;
class TableSummaryBannedTest extends TestCase
{
public function testFlagsTableWithSummaryAttribute(): void
{
$scanner = new Scanner();
$scanner->addRule(new TableSummaryBanned());
$violations = $scanner->scan('<div><table summary="This table lists details."><tr><td>Data</td></tr></table></div>');
$this->assertCount(1, $violations);
$this->assertSame('WCAG_1_3_1_TABLE_SUMMARY', $violations[0]->ruleId);
}
public function testPassesTableWithoutSummaryAttribute(): void
{
$scanner = new Scanner();
$scanner->addRule(new TableSummaryBanned());
$violations = $scanner->scan('<div><table><caption>Details</caption><tr><td>Data</td></tr></table></div>');
$this->assertCount(0, $violations);
}
}