diff --git a/tests/Unit/Livewire/Project/ProjectColorValidationTest.php b/tests/Unit/Livewire/Project/ProjectColorValidationTest.php new file mode 100644 index 000000000..fb0687407 --- /dev/null +++ b/tests/Unit/Livewire/Project/ProjectColorValidationTest.php @@ -0,0 +1,145 @@ +makePartial(); + $component->color = '#FF5733'; + $component->name = 'Test Project'; + $component->description = 'Test Description'; + + $rules = $component->rules(); + + expect($rules)->toHaveKey('color') + ->and($rules['color'])->toContain('nullable') + ->and($rules['color'])->toContain('string'); +}); + +it('accepts null color value', function () { + $component = Mockery::mock(Edit::class)->makePartial(); + $component->color = null; + $component->name = 'Test Project'; + $component->description = 'Test Description'; + + $rules = $component->rules(); + + expect($rules['color'])->toContain('nullable'); +}); + +it('color validation rules include regex pattern', function () { + $component = Mockery::mock(Edit::class)->makePartial(); + + $rules = $component->rules(); + + expect($rules) + ->toHaveKey('color') + ->and($rules['color']) + ->toBeArray() + ->and(count($rules['color']))->toBe(3) + ->and($rules['color'][0])->toBe('nullable') + ->and($rules['color'][1])->toBe('string') + ->and($rules['color'][2])->toBeString() + ->and($rules['color'][2])->toContain('regex:/^#[0-9A-Fa-f]{6}$/'); +}); + +it('has custom validation message for invalid color format', function () { + $component = Mockery::mock(Edit::class)->makePartial(); + + $messages = $component->messages(); + + expect($messages) + ->toHaveKey('color.regex') + ->and($messages['color.regex']) + ->toBeString() + ->toContain('#FF5733'); +}); + +it('syncs color from model to component', function () { + $project = Mockery::mock(Project::class)->makePartial(); + $project->shouldReceive('getAttribute') + ->with('name') + ->andReturn('Test Project'); + $project->shouldReceive('getAttribute') + ->with('description') + ->andReturn('Test Description'); + $project->shouldReceive('getAttribute') + ->with('color') + ->andReturn('#FF5733'); + + $project->name = 'Test Project'; + $project->description = 'Test Description'; + $project->color = '#FF5733'; + + $component = Mockery::mock(Edit::class)->makePartial(); + $component->project = $project; + + $component->syncData(false); + + expect($component->color)->toBe('#FF5733'); +}); + +it('syncs null color from model to component', function () { + $project = Mockery::mock(Project::class)->makePartial(); + $project->shouldReceive('getAttribute') + ->with('name') + ->andReturn('Test Project'); + $project->shouldReceive('getAttribute') + ->with('description') + ->andReturn('Test Description'); + $project->shouldReceive('getAttribute') + ->with('color') + ->andReturn(null); + + $project->name = 'Test Project'; + $project->description = 'Test Description'; + $project->color = null; + + $component = Mockery::mock(Edit::class)->makePartial(); + $component->project = $project; + + $component->syncData(false); + + expect($component->color)->toBeNull(); +}); + +it('syncs color from component to model', function () { + $project = Mockery::mock(Project::class); + $project->shouldReceive('update') + ->once() + ->with(Mockery::on(function ($data) { + return $data['color'] === '#00FF00' + && $data['name'] === 'Test Project' + && $data['description'] === 'Test Description'; + })); + + $component = Mockery::mock(Edit::class)->makePartial(); + $component->project = $project; + $component->name = 'Test Project'; + $component->description = 'Test Description'; + $component->color = '#00FF00'; + + $component->shouldReceive('validate')->once(); + + $component->syncData(true); +}); + +it('syncs null color from component to model', function () { + $project = Mockery::mock(Project::class); + $project->shouldReceive('update') + ->once() + ->with(Mockery::on(function ($data) { + return $data['color'] === null + && array_key_exists('color', $data); + })); + + $component = Mockery::mock(Edit::class)->makePartial(); + $component->project = $project; + $component->name = 'Test Project'; + $component->description = 'Test Description'; + $component->color = null; + + $component->shouldReceive('validate')->once(); + + $component->syncData(true); +}); diff --git a/tests/Unit/ProjectColorHexValidationTest.php b/tests/Unit/ProjectColorHexValidationTest.php new file mode 100644 index 000000000..c2917c27a --- /dev/null +++ b/tests/Unit/ProjectColorHexValidationTest.php @@ -0,0 +1,111 @@ +toBe(1); + } +}); + +test('hex color regex rejects invalid hex codes', function () { + $invalidColors = [ + '#FFF', // too short (3 chars) + '#FFFFFFF', // too long (7 chars) + 'FF5733', // missing hash + '#GG5733', // invalid character G + '#FF57ZZ', // invalid characters Z + '#12 34 56', // spaces + '#12-34-56', // dashes + 'rgb(255,0,0)', // not hex format + '#', // just hash + '', // empty string + '#FF57', // too short (4 chars) + '#FF5', // too short (3 chars) + ]; + + $pattern = '/^#[0-9A-Fa-f]{6}$/'; + + foreach ($invalidColors as $color) { + expect(preg_match($pattern, $color))->toBe(0); + } +}); + +test('hex color regex pattern is correctly formatted', function () { + $pattern = '/^#[0-9A-Fa-f]{6}$/'; + + // Verify the pattern itself is valid + expect(@preg_match($pattern, ''))->not->toBeFalse(); +}); + +test('hex color regex accepts common colors', function () { + $commonColors = [ + '#FF0000', // Red + '#00FF00', // Green (Lime) + '#0000FF', // Blue + '#FFFF00', // Yellow + '#FF00FF', // Magenta + '#00FFFF', // Cyan + '#000000', // Black + '#FFFFFF', // White + '#808080', // Gray + '#FFA500', // Orange + '#800080', // Purple + '#008000', // Dark Green + '#FFC0CB', // Pink + '#A52A2A', // Brown + ]; + + $pattern = '/^#[0-9A-Fa-f]{6}$/'; + + foreach ($commonColors as $color) { + expect(preg_match($pattern, $color))->toBe(1); + } +}); + +test('hex color regex rejects 3-char shorthand hex codes', function () { + // HTML supports 3-char hex (#FFF), but we require 6-char format + $shorthandColors = [ + '#FFF', // white shorthand + '#000', // black shorthand + '#F00', // red shorthand + '#0F0', // green shorthand + '#00F', // blue shorthand + ]; + + $pattern = '/^#[0-9A-Fa-f]{6}$/'; + + foreach ($shorthandColors as $color) { + expect(preg_match($pattern, $color))->toBe(0); + } +}); + +test('hex color regex rejects color names', function () { + $colorNames = [ + 'red', + 'blue', + 'green', + 'black', + 'white', + 'transparent', + ]; + + $pattern = '/^#[0-9A-Fa-f]{6}$/'; + + foreach ($colorNames as $color) { + expect(preg_match($pattern, $color))->toBe(0); + } +});