@@ -177,6 +177,138 @@ public function addRuleWithCompletePositionAddsRuleAndPreservesPosition(
177177 self ::assertSame (64 , $ ruleToAdd ->getColumnNumber (), 'column number not preserved ' );
178178 }
179179
180+ /**
181+ * @return array<string, array{0: non-empty-list<non-empty-string>, 1: int<0, max>}>
182+ */
183+ public static function provideInitialPropertyNamesAndSiblingIndex (): array
184+ {
185+ $ initialPropertyNamesSets = self ::providePropertyNamesToBeSetInitially ();
186+
187+ // Provide sets with each possible sibling index for the initially set `Rule`s.
188+ $ initialPropertyNamesAndSiblingIndexSets = [];
189+ foreach ($ initialPropertyNamesSets as $ setName => $ data ) {
190+ $ initialPropertyNames = $ data [0 ];
191+ for ($ siblingIndex = 0 ; $ siblingIndex < \count ($ initialPropertyNames ); ++$ siblingIndex ) {
192+ $ initialPropertyNamesAndSiblingIndexSets [$ setName . ', sibling index ' . $ siblingIndex ] =
193+ [$ initialPropertyNames , $ siblingIndex ];
194+ }
195+ }
196+
197+ return $ initialPropertyNamesAndSiblingIndexSets ;
198+ }
199+
200+ /**
201+ * @return DataProvider<string, array{0: non-empty-list<string>, 1: int<0, max>, 2: string}>
202+ */
203+ public static function provideInitialPropertyNamesAndSiblingIndexAndPropertyNameToAdd (): DataProvider
204+ {
205+ return DataProvider::cross (
206+ self ::provideInitialPropertyNamesAndSiblingIndex (),
207+ self ::providePropertyNameToAdd ()
208+ );
209+ }
210+
211+ /**
212+ * @test
213+ *
214+ * @param list<string> $initialPropertyNames
215+ * @param int<0, max> $siblingIndex
216+ *
217+ * @dataProvider provideInitialPropertyNamesAndSiblingIndexAndPropertyNameToAdd
218+ */
219+ public function addRuleWithSiblingInsertsRuleBeforeSibling (
220+ array $ initialPropertyNames ,
221+ int $ siblingIndex ,
222+ string $ propertyNameToAdd
223+ ): void {
224+ self ::markTestSkipped ('tofix: if property names don \'t match, sibling is ignored ' );
225+
226+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
227+ $ this ->setRulesFromPropertyNames ($ initialPropertyNames );
228+ $ sibling = $ this ->subject ->getRules ()[$ siblingIndex ];
229+
230+ $ this ->subject ->addRule ($ ruleToAdd , $ sibling );
231+
232+ $ rules = $ this ->subject ->getRules ();
233+ $ siblingPosition = \array_search ($ sibling , $ rules , true );
234+ self ::assertIsInt ($ siblingPosition );
235+ self ::assertSame ($ siblingPosition - 1 , \array_search ($ ruleToAdd , $ rules , true ));
236+ }
237+
238+ /**
239+ * @test
240+ *
241+ * @param list<string> $initialPropertyNames
242+ * @param int<0, max> $siblingIndex
243+ *
244+ * @dataProvider provideInitialPropertyNamesAndSiblingIndexAndPropertyNameToAdd
245+ */
246+ public function addRuleWithSiblingSetsValidLineNumber (
247+ array $ initialPropertyNames ,
248+ int $ siblingIndex ,
249+ string $ propertyNameToAdd
250+ ): void {
251+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
252+ $ this ->setRulesFromPropertyNames ($ initialPropertyNames );
253+ $ sibling = $ this ->subject ->getRules ()[$ siblingIndex ];
254+
255+ $ this ->subject ->addRule ($ ruleToAdd , $ sibling );
256+
257+ self ::assertIsInt ($ ruleToAdd ->getLineNumber (), 'line number not set ' );
258+ self ::assertGreaterThanOrEqual (1 , $ ruleToAdd ->getLineNumber (), 'line number not valid ' );
259+ }
260+
261+ /**
262+ * @test
263+ *
264+ * @param list<string> $initialPropertyNames
265+ * @param int<0, max> $siblingIndex
266+ *
267+ * @dataProvider provideInitialPropertyNamesAndSiblingIndexAndPropertyNameToAdd
268+ */
269+ public function addRuleWithSiblingSetsValidColumnNumber (
270+ array $ initialPropertyNames ,
271+ int $ siblingIndex ,
272+ string $ propertyNameToAdd
273+ ): void {
274+ self ::markTestSkipped ('tofix: sometimes a negative column number results ' );
275+
276+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
277+ $ this ->setRulesFromPropertyNames ($ initialPropertyNames );
278+ $ sibling = $ this ->subject ->getRules ()[$ siblingIndex ];
279+
280+ $ this ->subject ->addRule ($ ruleToAdd , $ sibling );
281+
282+ self ::assertIsInt ($ ruleToAdd ->getColumnNumber (), 'column number not set ' );
283+ self ::assertGreaterThanOrEqual (0 , $ ruleToAdd ->getColumnNumber (), 'column number not valid ' );
284+ }
285+
286+ /**
287+ * @test
288+ *
289+ * @param list<string> $initialPropertyNames
290+ *
291+ * @dataProvider provideInitialPropertyNamesAndPropertyNameToAdd
292+ */
293+ public function addRuleWithSiblingNotInRuleSetAddsRuleAfterInitialRulesAndSetsValidLineAndColumnNumbers (
294+ array $ initialPropertyNames ,
295+ string $ propertyNameToAdd
296+ ): void {
297+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
298+ $ this ->setRulesFromPropertyNames ($ initialPropertyNames );
299+
300+ // `display` is sometimes in `$initialPropertyNames` and sometimes the `$propertyNameToAdd`.
301+ // Choosing this for the bogus sibling allows testing all combinations of whether it is or isn't.
302+ $ this ->subject ->addRule ($ ruleToAdd , new Rule ('display ' ));
303+
304+ $ rules = $ this ->subject ->getRules ();
305+ self ::assertSame ($ ruleToAdd , \end ($ rules ));
306+ self ::assertIsInt ($ ruleToAdd ->getLineNumber (), 'line number not set ' );
307+ self ::assertGreaterThanOrEqual (1 , $ ruleToAdd ->getLineNumber (), 'line number not valid ' );
308+ self ::assertIsInt ($ ruleToAdd ->getColumnNumber (), 'column number not set ' );
309+ self ::assertGreaterThanOrEqual (0 , $ ruleToAdd ->getColumnNumber (), 'column number not valid ' );
310+ }
311+
180312 /**
181313 * @return array<string, array{0: list<string>, 1: string, 2: list<string>}>
182314 */
0 commit comments