Git Komut Rehberi & Terminal Asistanı
Sıfırdan Yeni Bir Depo Başlatın:
Mevcut Bir Git Deposu veya Klasörü Gönderin:
Hataları Geri Alma, İptal & Temizlik:
Son commit'i geri al (yapılan değişiklikleri korur):
git reset --soft HEAD~1
Yapılan yerel değişiklikleri iptal et (çalışma ağacını temizler):
git restore .
Takip edilmeyen gereksiz dosyaları sil:
git clean -fd
Değişiklikleri geçici sakla ve geri getir (stash):
git stash git stash pop
Dal (Branch) ve Sürüm Etiketleri:
Yeni dal aç ve geçiş yap:
git checkout -b yeni-ozellik git push -u origin yeni-ozellik
Sürüm etiketi (tag) oluştur ve gönder:
git tag -a v1.0.0 -m "Sürüm 1.0.0" git push origin --tags
feat(v3.3.0): enterprise presets, badges, notifications, rule controller, watch mode, offline healer, and WCAG 2.2 ruleset
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\AutoFix;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Core\SelfHealing\LocalHealer;
|
||||
use YakNet\AccessibilityConsole\Core\Severity;
|
||||
use YakNet\AccessibilityConsole\Core\Violation;
|
||||
use YakNet\AccessibilityConsole\Core\WCAGStandard;
|
||||
|
||||
class LocalHealerTest extends TestCase
|
||||
{
|
||||
private LocalHealer $healer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->healer = new LocalHealer();
|
||||
}
|
||||
|
||||
public function testHealsMissingImgAlt(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_1_1_1_IMG_ALT',
|
||||
'Image missing alt',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<img src="photo.jpg">'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringContainsString('FIX: <img alt="" src="photo.jpg">', $healed);
|
||||
}
|
||||
|
||||
public function testHealsDecorativeSvg(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_1_1_1_SVG',
|
||||
'SVG needs accessible text',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<svg class="icon"><path d="..."/></svg>'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringContainsString('FIX: <svg aria-hidden="true" class="icon">', $healed);
|
||||
}
|
||||
|
||||
public function testHealsTargetBlankLinkRel(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_LINK_TARGET_BLANK',
|
||||
'Target blank missing noopener',
|
||||
Severity::WARNING,
|
||||
WCAGStandard::A,
|
||||
'<a href="https://example.com" target="_blank">External</a>'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringContainsString('rel="noopener noreferrer"', $healed);
|
||||
}
|
||||
|
||||
public function testHealsPositiveTabindex(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_2_4_3_TABINDEX',
|
||||
'Avoid positive tabindex',
|
||||
Severity::WARNING,
|
||||
WCAGStandard::A,
|
||||
'<button tabindex="5">Submit</button>'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringContainsString('tabindex="0"', $healed);
|
||||
}
|
||||
|
||||
public function testHealsInvalidTableScope(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_1_3_1_TABLE_SCOPE',
|
||||
'Scope only on headers',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<td scope="col">Data cell</td>'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringNotContainsString('scope=', $healed);
|
||||
}
|
||||
|
||||
public function testHealsMetaRefresh(): void
|
||||
{
|
||||
$violation = new Violation(
|
||||
'WCAG_2_2_1_META_REFRESH',
|
||||
'Meta refresh banned',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<meta http-equiv="refresh" content="30">'
|
||||
);
|
||||
|
||||
$healed = $this->healer->heal($violation);
|
||||
$this->assertNotNull($healed);
|
||||
$this->assertStringContainsString('<!-- <meta http-equiv="refresh" content="30"> (Removed', $healed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Badges;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Badges\BadgeGenerator;
|
||||
|
||||
class BadgeGeneratorTest extends TestCase
|
||||
{
|
||||
public function testGeneratesValidScoreBadgeSvg(): void
|
||||
{
|
||||
$svg = BadgeGenerator::generateScoreBadge(95);
|
||||
|
||||
$this->assertStringContainsString('<svg', $svg);
|
||||
$this->assertStringContainsString('</svg>', $svg);
|
||||
$this->assertStringContainsString('accessibility', $svg);
|
||||
$this->assertStringContainsString('95/100', $svg);
|
||||
$this->assertStringContainsString('#10b981', $svg); // green color for >= 90
|
||||
}
|
||||
|
||||
public function testGeneratesWarningScoreBadgeSvg(): void
|
||||
{
|
||||
$svg = BadgeGenerator::generateScoreBadge(65);
|
||||
|
||||
$this->assertStringContainsString('65/100', $svg);
|
||||
$this->assertStringContainsString('#ef4444', $svg); // red color for < 70
|
||||
}
|
||||
|
||||
public function testGeneratesComplianceBadge(): void
|
||||
{
|
||||
$svg = BadgeGenerator::generateComplianceBadge('WCAG 2.1 AA', true);
|
||||
|
||||
$this->assertStringContainsString('WCAG 2.1 AA', $svg);
|
||||
$this->assertStringContainsString('passed', $svg);
|
||||
}
|
||||
|
||||
public function testGeneratesViolationsBadge(): void
|
||||
{
|
||||
$svg = BadgeGenerator::generateViolationsBadge(0);
|
||||
$this->assertStringContainsString('0 issues', $svg);
|
||||
|
||||
$svgIssues = BadgeGenerator::generateViolationsBadge(4);
|
||||
$this->assertStringContainsString('4 issues', $svgIssues);
|
||||
}
|
||||
|
||||
public function testGeneratesBadgeWithCustomOptions(): void
|
||||
{
|
||||
$options = new \YakNet\AccessibilityConsole\Badges\BadgeOptions(
|
||||
label: 'custom-a11y',
|
||||
leftColor: '#003366',
|
||||
rightColor: '#00cc66',
|
||||
borderRadius: 6
|
||||
);
|
||||
|
||||
$svg = BadgeGenerator::generateScoreBadge(88, $options);
|
||||
$this->assertStringContainsString('custom-a11y', $svg);
|
||||
$this->assertStringContainsString('#003366', $svg);
|
||||
$this->assertStringContainsString('#00cc66', $svg);
|
||||
$this->assertStringContainsString('rx="6"', $svg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Console;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use YakNet\AccessibilityConsole\Console\Command\RulesCommand;
|
||||
|
||||
class RulesCommandTest extends TestCase
|
||||
{
|
||||
public function testListAllRules(): void
|
||||
{
|
||||
$command = new RulesCommand();
|
||||
$tester = new CommandTester($command);
|
||||
|
||||
$exitCode = $tester->execute([]);
|
||||
|
||||
$this->assertSame(0, $exitCode);
|
||||
$output = $tester->getDisplay();
|
||||
$this->assertStringContainsString('Accessibility Console - Available Rules', $output);
|
||||
$this->assertStringContainsString('Total rules available: 130', $output);
|
||||
}
|
||||
|
||||
public function testFilterRulesBySearch(): void
|
||||
{
|
||||
$command = new RulesCommand();
|
||||
$tester = new CommandTester($command);
|
||||
|
||||
$exitCode = $tester->execute([
|
||||
'--search' => 'contrast',
|
||||
]);
|
||||
|
||||
$this->assertSame(0, $exitCode);
|
||||
$output = $tester->getDisplay();
|
||||
$this->assertStringContainsString('WCAG_1_4_3_CONTRAST', $output);
|
||||
$this->assertStringContainsString('Showing', $output);
|
||||
}
|
||||
|
||||
public function testFilterRulesByStandardAndLevel(): void
|
||||
{
|
||||
$command = new RulesCommand();
|
||||
$tester = new CommandTester($command);
|
||||
|
||||
$exitCode = $tester->execute([
|
||||
'--standard' => 'AA',
|
||||
]);
|
||||
|
||||
$this->assertSame(0, $exitCode);
|
||||
$output = $tester->getDisplay();
|
||||
$this->assertStringContainsString('AA', $output);
|
||||
$this->assertStringContainsString('Showing', $output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Console;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use YakNet\AccessibilityConsole\Console\Command\WatchCommand;
|
||||
|
||||
class WatchCommandTest extends TestCase
|
||||
{
|
||||
public function testWatchCommandRunsInitialScanAndExitsWithMaxIterations(): void
|
||||
{
|
||||
$command = new WatchCommand();
|
||||
$tester = new CommandTester($command);
|
||||
|
||||
$exitCode = $tester->execute([
|
||||
'target' => 'demo/views-fixed/home.php',
|
||||
'--max-iterations' => '1',
|
||||
'--interval' => '1',
|
||||
]);
|
||||
|
||||
$this->assertSame(0, $exitCode);
|
||||
$output = $tester->getDisplay();
|
||||
$this->assertStringContainsString('Accessibility Console - Real-Time Watch Mode', $output);
|
||||
$this->assertStringContainsString('Initial Scan', $output);
|
||||
$this->assertStringContainsString('Health Score:', $output);
|
||||
}
|
||||
|
||||
public function testDetectChangedFiles(): void
|
||||
{
|
||||
$command = new WatchCommand();
|
||||
|
||||
$old = [
|
||||
'file1.php' => 100,
|
||||
'file2.php' => 200,
|
||||
];
|
||||
|
||||
$new = [
|
||||
'file1.php' => 100,
|
||||
'file2.php' => 205, // modified
|
||||
'file3.php' => 300, // added
|
||||
];
|
||||
|
||||
$changed = $command->detectChangedFiles($old, $new);
|
||||
$this->assertContains('file2.php', $changed);
|
||||
$this->assertContains('file3.php', $changed);
|
||||
$this->assertNotContains('file1.php', $changed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Notifications;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Notifications\NotificationDispatcher;
|
||||
use YakNet\AccessibilityConsole\Notifications\NotificationPayload;
|
||||
use YakNet\AccessibilityConsole\Notifications\NotifierInterface;
|
||||
|
||||
class NotificationDispatcherTest extends TestCase
|
||||
{
|
||||
public function testDispatchToMultipleNotifiers(): void
|
||||
{
|
||||
$dispatcher = new NotificationDispatcher();
|
||||
|
||||
$mockSlack = $this->createMock(NotifierInterface::class);
|
||||
$mockSlack->expects($this->once())
|
||||
->method('send')
|
||||
->willReturn(true);
|
||||
|
||||
$mockDiscord = $this->createMock(NotifierInterface::class);
|
||||
$mockDiscord->expects($this->once())
|
||||
->method('send')
|
||||
->willReturn(true);
|
||||
|
||||
$dispatcher->addNotifier('slack', $mockSlack);
|
||||
$dispatcher->addNotifier('discord', $mockDiscord);
|
||||
|
||||
$this->assertTrue($dispatcher->hasNotifiers());
|
||||
|
||||
$payload = new NotificationPayload('https://example.com', 95, 2, 0, 2);
|
||||
$results = $dispatcher->dispatch($payload);
|
||||
|
||||
$this->assertTrue($results['slack']);
|
||||
$this->assertTrue($results['discord']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Presets;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Presets\PresetRegistry;
|
||||
use YakNet\AccessibilityConsole\Presets\Section508Preset;
|
||||
use YakNet\AccessibilityConsole\Presets\En301549Preset;
|
||||
use YakNet\AccessibilityConsole\Presets\ECommercePreset;
|
||||
|
||||
class PresetRegistryTest extends TestCase
|
||||
{
|
||||
public function testRegistryLoadsDefaultPresets(): void
|
||||
{
|
||||
$registry = new PresetRegistry();
|
||||
$all = $registry->all();
|
||||
|
||||
$this->assertArrayHasKey('section508', $all);
|
||||
$this->assertArrayHasKey('en301549', $all);
|
||||
$this->assertArrayHasKey('ecommerce', $all);
|
||||
}
|
||||
|
||||
public function testGetPresetByName(): void
|
||||
{
|
||||
$registry = new PresetRegistry();
|
||||
|
||||
$preset = $registry->get('section508');
|
||||
$this->assertInstanceOf(Section508Preset::class, $preset);
|
||||
$this->assertSame(3, $preset->getLevel());
|
||||
|
||||
$ecommerce = $registry->get('ecommerce');
|
||||
$this->assertInstanceOf(ECommercePreset::class, $ecommerce);
|
||||
$this->assertContains('WCAG_3_3_7_REDUNDANT_ENTRY', $ecommerce->getIncludedRules());
|
||||
}
|
||||
|
||||
public function testGetNonExistentPresetReturnsNull(): void
|
||||
{
|
||||
$registry = new PresetRegistry();
|
||||
$this->assertNull($registry->get('non_existent'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Reporting;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use YakNet\AccessibilityConsole\Core\Severity;
|
||||
use YakNet\AccessibilityConsole\Core\Violation;
|
||||
use YakNet\AccessibilityConsole\Core\WCAGStandard;
|
||||
use YakNet\AccessibilityConsole\Reporting\JunitFormatter;
|
||||
|
||||
class JunitFormatterTest extends TestCase
|
||||
{
|
||||
public function testRendersValidJunitXmlWithViolations(): void
|
||||
{
|
||||
$formatter = new JunitFormatter();
|
||||
$violations = [
|
||||
new Violation(
|
||||
'WCAG_1_1_1_IMG_ALT',
|
||||
'Images must have alternative text.',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<img src="photo.png">',
|
||||
['file' => 'views/index.php', 'line' => 10, 'column' => 2]
|
||||
),
|
||||
];
|
||||
|
||||
$xml = $formatter->render($violations);
|
||||
$this->assertStringContainsString('<?xml version="1.0" encoding="UTF-8"?>', $xml);
|
||||
$this->assertStringContainsString('<testsuites', $xml);
|
||||
$this->assertStringContainsString('failures="1"', $xml);
|
||||
$this->assertStringContainsString('<failure', $xml);
|
||||
$this->assertStringContainsString('WCAG_1_1_1_IMG_ALT', $xml);
|
||||
|
||||
// Verify valid XML parsing
|
||||
$dom = new \DOMDocument();
|
||||
$this->assertTrue($dom->loadXML($xml));
|
||||
}
|
||||
|
||||
public function testRendersCleanXmlWhenEmpty(): void
|
||||
{
|
||||
$formatter = new JunitFormatter();
|
||||
$input = new ArrayInput([]);
|
||||
$output = new BufferedOutput();
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$exitCode = $formatter->format([], 0, $io);
|
||||
$this->assertSame(0, $exitCode);
|
||||
|
||||
$xml = $output->fetch();
|
||||
$this->assertStringContainsString('failures="0"', $xml);
|
||||
$this->assertStringContainsString('AccessibilityCompliant', $xml);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Reporting;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use YakNet\AccessibilityConsole\Core\Severity;
|
||||
use YakNet\AccessibilityConsole\Core\Violation;
|
||||
use YakNet\AccessibilityConsole\Core\WCAGStandard;
|
||||
use YakNet\AccessibilityConsole\Reporting\SarifFormatter;
|
||||
|
||||
class SarifFormatterTest extends TestCase
|
||||
{
|
||||
public function testRendersValidSarifJson(): void
|
||||
{
|
||||
$formatter = new SarifFormatter();
|
||||
$violations = [
|
||||
new Violation(
|
||||
'WCAG_1_1_1_IMG_ALT',
|
||||
'Images must have alternative text.',
|
||||
Severity::ERROR,
|
||||
WCAGStandard::A,
|
||||
'<img src="test.jpg">',
|
||||
['file' => 'templates/home.blade.php', 'line' => 14, 'column' => 5],
|
||||
'Add alt="" attribute'
|
||||
),
|
||||
new Violation(
|
||||
'WCAG_1_4_3_CONTRAST',
|
||||
'Insufficient color contrast.',
|
||||
Severity::WARNING,
|
||||
WCAGStandard::AA,
|
||||
'<span style="color:#ccc">Text</span>',
|
||||
['file' => 'templates/home.blade.php', 'line' => 20, 'column' => 1]
|
||||
),
|
||||
];
|
||||
|
||||
$json = $formatter->render($violations);
|
||||
$this->assertJson($json);
|
||||
|
||||
$decoded = json_decode($json, true);
|
||||
$this->assertIsArray($decoded);
|
||||
$this->assertSame('2.1.0', $decoded['version']);
|
||||
$this->assertSame('YakNet Accessibility Console', $decoded['runs'][0]['tool']['driver']['name']);
|
||||
$this->assertCount(2, $decoded['runs'][0]['results']);
|
||||
|
||||
$firstResult = $decoded['runs'][0]['results'][0];
|
||||
$this->assertSame('WCAG_1_1_1_IMG_ALT', $firstResult['ruleId']);
|
||||
$this->assertSame('error', $firstResult['level']);
|
||||
$this->assertSame('templates/home.blade.php', $firstResult['locations'][0]['physicalLocation']['artifactLocation']['uri']);
|
||||
$this->assertSame(14, $firstResult['locations'][0]['physicalLocation']['region']['startLine']);
|
||||
}
|
||||
|
||||
public function testFormatOutputsToSymfonyStyle(): void
|
||||
{
|
||||
$formatter = new SarifFormatter();
|
||||
$violations = [];
|
||||
|
||||
$input = new ArrayInput([]);
|
||||
$output = new BufferedOutput();
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$exitCode = $formatter->format($violations, 0, $io);
|
||||
$this->assertSame(0, $exitCode);
|
||||
|
||||
$content = $output->fetch();
|
||||
$this->assertJson($content);
|
||||
$decoded = json_decode($content, true);
|
||||
$this->assertIsArray($decoded);
|
||||
$this->assertEmpty($decoded['runs'][0]['results']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Core\Scanner;
|
||||
use YakNet\AccessibilityConsole\Rules\LabelInName;
|
||||
|
||||
class LabelInNameTest extends TestCase
|
||||
{
|
||||
public function testFlagsButtonWhoseAriaLabelDoesNotContainVisibleText(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new LabelInName());
|
||||
|
||||
$html = '<button aria-label="Send Form">Submit</button>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame('WCAG_2_5_3_LABEL_IN_NAME', $violations[0]->ruleId);
|
||||
$this->assertStringContainsString('Submit', $violations[0]->message);
|
||||
}
|
||||
|
||||
public function testPassesButtonWhoseAriaLabelContainsVisibleText(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new LabelInName());
|
||||
|
||||
$html = '<button aria-label="Submit this inquiry">Submit</button>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
public function testPassesButtonWithoutExplicitAriaLabel(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new LabelInName());
|
||||
|
||||
$html = '<button>Click Here</button>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
public function testFlagsLinkWhoseAriaLabelDiffersFromVisibleText(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new LabelInName());
|
||||
|
||||
$html = '<a href="/contact" aria-label="Reach out to support">Contact Us</a>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(1, $violations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Core\Scanner;
|
||||
use YakNet\AccessibilityConsole\Rules\RedundantEntry;
|
||||
|
||||
class RedundantEntryTest extends TestCase
|
||||
{
|
||||
public function testFlagsFormWithShippingAndBillingWithoutSameAsCheckbox(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new RedundantEntry());
|
||||
|
||||
$html = '<form>
|
||||
<input type="text" name="shipping_address" id="shipping_address">
|
||||
<input type="text" name="shipping_city" id="shipping_city">
|
||||
<input type="text" name="billing_address" id="billing_address">
|
||||
<input type="text" name="billing_city" id="billing_city">
|
||||
</form>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame('WCAG_3_3_7_REDUNDANT_ENTRY', $violations[0]->ruleId);
|
||||
}
|
||||
|
||||
public function testPassesFormWithSameAsShippingCheckbox(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new RedundantEntry());
|
||||
|
||||
$html = '<form>
|
||||
<input type="text" name="shipping_address" id="shipping_address">
|
||||
<input type="text" name="shipping_city" id="shipping_city">
|
||||
<label><input type="checkbox" name="same_as_shipping"> Billing same as shipping</label>
|
||||
<input type="text" name="billing_address" id="billing_address">
|
||||
<input type="text" name="billing_city" id="billing_city">
|
||||
</form>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Core\Severity;
|
||||
use YakNet\AccessibilityConsole\Core\WCAGStandard;
|
||||
use YakNet\AccessibilityConsole\Rules\RuleController;
|
||||
|
||||
class RuleControllerTest extends TestCase
|
||||
{
|
||||
public function testInitializesAndRetrievesRule(): void
|
||||
{
|
||||
$controller = new RuleController();
|
||||
$this->assertGreaterThanOrEqual(130, $controller->count());
|
||||
|
||||
$rule = $controller->getRule('WCAG_2_5_3_LABEL_IN_NAME');
|
||||
$this->assertNotNull($rule);
|
||||
}
|
||||
|
||||
public function testFilterByStandard(): void
|
||||
{
|
||||
$controller = new RuleController();
|
||||
$aaRules = $controller->filterByStandard(WCAGStandard::AA);
|
||||
|
||||
$this->assertNotEmpty($aaRules);
|
||||
foreach ($aaRules as $rule) {
|
||||
$this->assertSame(WCAGStandard::AA, $rule->getStandard());
|
||||
}
|
||||
}
|
||||
|
||||
public function testFilterBySeverity(): void
|
||||
{
|
||||
$controller = new RuleController();
|
||||
$errorRules = $controller->filterBySeverity(Severity::ERROR);
|
||||
|
||||
$this->assertNotEmpty($errorRules);
|
||||
foreach ($errorRules as $rule) {
|
||||
$this->assertSame(Severity::ERROR, $rule->getSeverity());
|
||||
}
|
||||
}
|
||||
|
||||
public function testExecuteRuleDirectlyOnDomElement(): void
|
||||
{
|
||||
$controller = new RuleController();
|
||||
|
||||
$dom = new \DOMDocument();
|
||||
$dom->loadHTML('<button aria-label="Cancel">Submit</button>');
|
||||
$button = $dom->getElementsByTagName('button')->item(0);
|
||||
$this->assertInstanceOf(\DOMElement::class, $button);
|
||||
|
||||
$violation = $controller->executeRule('WCAG_2_5_3_LABEL_IN_NAME', $button);
|
||||
$this->assertNotNull($violation);
|
||||
$this->assertSame('WCAG_2_5_3_LABEL_IN_NAME', $violation->ruleId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Rules\RuleExecutionStats;
|
||||
|
||||
class RuleExecutionStatsTest extends TestCase
|
||||
{
|
||||
public function testRecordAndRetrieveStats(): void
|
||||
{
|
||||
$stats = new RuleExecutionStats();
|
||||
|
||||
$stats->record('WCAG_1_1_1_IMG_ALT', 2.5, true);
|
||||
$stats->record('WCAG_1_1_1_IMG_ALT', 1.5, false);
|
||||
$stats->record('WCAG_1_4_3_CONTRAST', 10.0, true);
|
||||
|
||||
$all = $stats->getAllStats();
|
||||
$this->assertSame(2, $all['WCAG_1_1_1_IMG_ALT']['invocations']);
|
||||
$this->assertSame(4.0, $all['WCAG_1_1_1_IMG_ALT']['total_time_ms']);
|
||||
$this->assertSame(1, $all['WCAG_1_1_1_IMG_ALT']['violations']);
|
||||
|
||||
$slowest = $stats->getSlowestRules(1);
|
||||
$this->assertArrayHasKey('WCAG_1_4_3_CONTRAST', $slowest);
|
||||
$this->assertSame(10.0, $slowest['WCAG_1_4_3_CONTRAST']['total_time_ms']);
|
||||
}
|
||||
|
||||
public function testResetStats(): void
|
||||
{
|
||||
$stats = new RuleExecutionStats();
|
||||
$stats->record('WCAG_1_1_1_IMG_ALT', 5.0, true);
|
||||
$this->assertNotEmpty($stats->getAllStats());
|
||||
|
||||
$stats->reset();
|
||||
$this->assertEmpty($stats->getAllStats());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace YakNet\AccessibilityConsole\Tests\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use YakNet\AccessibilityConsole\Core\Scanner;
|
||||
use YakNet\AccessibilityConsole\Rules\TextSpacing;
|
||||
|
||||
class TextSpacingTest extends TestCase
|
||||
{
|
||||
public function testFlagsConstrainedLineHeight(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new TextSpacing());
|
||||
|
||||
$html = '<p style="line-height: 1; font-size: 16px;">This text has insufficient line height.</p>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame('WCAG_1_4_12_TEXT_SPACING', $violations[0]->ruleId);
|
||||
}
|
||||
|
||||
public function testPassesAdequateLineHeight(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new TextSpacing());
|
||||
|
||||
$html = '<p style="line-height: 1.6; font-size: 16px;">Proper line height content.</p>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
public function testFlagsFixedHeightWithOverflowHiddenOnText(): void
|
||||
{
|
||||
$scanner = new Scanner();
|
||||
$scanner->addRule(new TextSpacing());
|
||||
|
||||
$html = '<div style="height: 30px; overflow: hidden;"><p>This is a long paragraph that might be clipped when spacing is enlarged by the user in accessible mode.</p></div>';
|
||||
$violations = $scanner->scan($html);
|
||||
|
||||
$this->assertCount(1, $violations);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user