getSize())->toBe(21) ->and($matrix->getVersion()->getVersionNumber())->toBe(1); }); test('empty matrix has all light modules', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $module = $matrix->getModuleAt(0, 0); expect($module->isLight())->toBeTrue(); }); test('can set and get module', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $position = ModulePosition::at(5, 5); $matrix = $matrix->setModule($position, Module::dark()); expect($matrix->getModule($position)->isDark())->toBeTrue(); }); test('setting module returns new instance', function () { $version = QrCodeVersion::fromNumber(1); $matrix1 = QrCodeMatrix::create($version); $position = ModulePosition::at(5, 5); $matrix2 = $matrix1->setModule($position, Module::dark()); // Original matrix unchanged (immutability) expect($matrix1->getModule($position)->isLight())->toBeTrue() ->and($matrix2->getModule($position)->isDark())->toBeTrue(); }); test('can set module using coordinates', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $matrix = $matrix->setModuleAt(10, 10, Module::dark()); expect($matrix->getModuleAt(10, 10)->isDark())->toBeTrue(); }); test('can use helper methods setDark and setLight', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $pos1 = ModulePosition::at(5, 5); $pos2 = ModulePosition::at(10, 10); $matrix = $matrix->setDark($pos1); $matrix = $matrix->setLight($pos2); expect($matrix->getModule($pos1)->isDark())->toBeTrue() ->and($matrix->getModule($pos2)->isLight())->toBeTrue(); }); test('can check if position is dark', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $position = ModulePosition::at(5, 5); $matrix = $matrix->setDark($position); expect($matrix->isDark($position))->toBeTrue(); }); test('throws exception for out of bounds position', function () { $version = QrCodeVersion::fromNumber(1); // Size = 21 $matrix = QrCodeMatrix::create($version); $position = ModulePosition::at(25, 25); // Out of bounds $matrix->getModule($position); })->throws(\App\Framework\Exception\FrameworkException::class); test('can convert to array', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $array = $matrix->toArray(); expect($array)->toBeArray() ->and(count($array))->toBe(21) ->and(count($array[0]))->toBe(21); }); test('can convert to binary string', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $matrix = $matrix->setModuleAt(0, 0, Module::dark()); $matrix = $matrix->setModuleAt(0, 1, Module::light()); $binary = $matrix->toBinaryString(); expect($binary)->toBeString() ->and($binary)->toContain('1') ->and($binary)->toContain('0') ->and($binary)->toContain("\n"); }); test('can convert to ASCII art', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); $matrix = $matrix->setModuleAt(0, 0, Module::dark()); $matrix = $matrix->setModuleAt(0, 1, Module::light()); $ascii = $matrix->toAsciiArt(); expect($ascii)->toBeString() ->and($ascii)->toContain('█') ->and($ascii)->toContain('░'); }); test('can count dark modules', function () { $version = QrCodeVersion::fromNumber(1); $matrix = QrCodeMatrix::create($version); // Add some dark modules $matrix = $matrix->setModuleAt(0, 0, Module::dark()); $matrix = $matrix->setModuleAt(1, 1, Module::dark()); $matrix = $matrix->setModuleAt(2, 2, Module::dark()); $count = $matrix->countDarkModules(); expect($count)->toBe(3); }); test('matrix size scales with version', function () { $matrix1 = QrCodeMatrix::create(QrCodeVersion::fromNumber(1)); $matrix2 = QrCodeMatrix::create(QrCodeVersion::fromNumber(2)); $matrix3 = QrCodeMatrix::create(QrCodeVersion::fromNumber(3)); expect($matrix1->getSize())->toBe(21) ->and($matrix2->getSize())->toBe(25) ->and($matrix3->getSize())->toBe(29); });