Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Tests\Unit\Validation;
4
5use Orchestra\Testbench\TestCase;
6use SocialDept\AtpSchema\Validation\ValidationError;
7
8class ValidationErrorTest extends TestCase
9{
10 public function test_it_creates_simple_error(): void
11 {
12 $error = ValidationError::make('field', 'Field is required');
13
14 $this->assertEquals('field', $error->getField());
15 $this->assertEquals('Field is required', $error->getMessage());
16 $this->assertNull($error->getRule());
17 }
18
19 public function test_it_creates_error_with_rule(): void
20 {
21 $error = ValidationError::withRule('field', 'Field is required', 'required');
22
23 $this->assertEquals('field', $error->getField());
24 $this->assertEquals('Field is required', $error->getMessage());
25 $this->assertEquals('required', $error->getRule());
26 }
27
28 public function test_it_creates_error_with_full_context(): void
29 {
30 $error = ValidationError::withContext(
31 'age',
32 'Value exceeds maximum',
33 'max',
34 100,
35 150
36 );
37
38 $this->assertEquals('age', $error->getField());
39 $this->assertEquals('Value exceeds maximum', $error->getMessage());
40 $this->assertEquals('max', $error->getRule());
41 $this->assertEquals(100, $error->getExpected());
42 $this->assertEquals(150, $error->getActual());
43 }
44
45 public function test_it_checks_if_has_rule(): void
46 {
47 $withRule = ValidationError::withRule('field', 'message', 'required');
48 $withoutRule = ValidationError::make('field', 'message');
49
50 $this->assertTrue($withRule->hasRule());
51 $this->assertFalse($withoutRule->hasRule());
52 }
53
54 public function test_it_checks_if_has_expected(): void
55 {
56 $withExpected = ValidationError::withContext('field', 'message', 'max', 100);
57 $withoutExpected = ValidationError::make('field', 'message');
58
59 $this->assertTrue($withExpected->hasExpected());
60 $this->assertFalse($withoutExpected->hasExpected());
61 }
62
63 public function test_it_checks_if_has_actual(): void
64 {
65 $withActual = ValidationError::withContext('field', 'message', 'type', 'string', 'integer');
66 $withoutActual = ValidationError::make('field', 'message');
67
68 $this->assertTrue($withActual->hasActual());
69 $this->assertFalse($withoutActual->hasActual());
70 }
71
72 public function test_it_converts_to_array(): void
73 {
74 $error = ValidationError::withContext(
75 'field',
76 'message',
77 'max',
78 100,
79 150,
80 ['extra' => 'data']
81 );
82
83 $array = $error->toArray();
84
85 $this->assertEquals('field', $array['field']);
86 $this->assertEquals('message', $array['message']);
87 $this->assertEquals('max', $array['rule']);
88 $this->assertEquals(100, $array['expected']);
89 $this->assertEquals(150, $array['actual']);
90 $this->assertEquals(['extra' => 'data'], $array['context']);
91 }
92
93 public function test_it_converts_simple_error_to_array(): void
94 {
95 $error = ValidationError::make('field', 'message');
96
97 $array = $error->toArray();
98
99 $this->assertEquals(['field' => 'field', 'message' => 'message'], $array);
100 }
101
102 public function test_it_converts_to_json(): void
103 {
104 $error = ValidationError::withRule('field', 'message', 'required');
105
106 $json = json_encode($error);
107 $decoded = json_decode($json, true);
108
109 $this->assertEquals('field', $decoded['field']);
110 $this->assertEquals('message', $decoded['message']);
111 $this->assertEquals('required', $decoded['rule']);
112 }
113
114 public function test_it_converts_to_string(): void
115 {
116 $error = ValidationError::make('username', 'Username is required');
117
118 $this->assertEquals('username: Username is required', (string) $error);
119 }
120
121 public function test_it_stores_context_data(): void
122 {
123 $error = ValidationError::withContext(
124 'field',
125 'message',
126 'rule',
127 null,
128 null,
129 ['path' => '$.user.name', 'constraint' => 'maxLength']
130 );
131
132 $context = $error->getContext();
133
134 $this->assertEquals('$.user.name', $context['path']);
135 $this->assertEquals('maxLength', $context['constraint']);
136 }
137
138 public function test_it_handles_null_values(): void
139 {
140 $error = new ValidationError('field', 'message', null);
141
142 $this->assertNull($error->getRule());
143 $this->assertFalse($error->hasExpected());
144 $this->assertFalse($error->hasActual());
145 $this->assertEmpty($error->getContext());
146 }
147
148 public function test_it_handles_explicitly_null_values(): void
149 {
150 $error = new ValidationError('field', 'message', 'rule', null, null, []);
151
152 $this->assertNull($error->getExpected());
153 $this->assertNull($error->getActual());
154 $this->assertTrue($error->hasExpected());
155 $this->assertTrue($error->hasActual());
156 }
157
158 public function test_it_provides_readonly_access_to_properties(): void
159 {
160 $error = ValidationError::make('field', 'message');
161
162 $this->assertEquals('field', $error->field);
163 $this->assertEquals('message', $error->message);
164 $this->assertNull($error->rule);
165 $this->assertNull($error->expected);
166 $this->assertNull($error->actual);
167 $this->assertEmpty($error->context);
168 }
169}