99use Sabberworm \CSS \Rule \Rule ;
1010use Sabberworm \CSS \RuleSet \RuleSet ;
1111use Sabberworm \CSS \Tests \Unit \RuleSet \Fixtures \ConcreteRuleSet ;
12+ use TRegx \DataProvider \DataProviders ;
1213
1314/**
1415 * @covers \Sabberworm\CSS\RuleSet\RuleSet
@@ -27,6 +28,148 @@ public function implementsCSSElement()
2728 self ::assertInstanceOf (CSSElement::class, $ subject );
2829 }
2930
31+ /**
32+ * @return array<string, array{0: list<non-empty-string>}>
33+ */
34+ public static function providePropertyNamesToBeSetInitially ()
35+ {
36+ return [
37+ 'no properties ' => [[]],
38+ 'one property ' => [['color ' ]],
39+ 'two different properties ' => [['color ' , 'display ' ]],
40+ 'two of the same property ' => [['color ' , 'color ' ]],
41+ ];
42+ }
43+
44+ /**
45+ * @return array<string, array{0: non-empty-string}>
46+ */
47+ public static function providePropertyNameToAdd ()
48+ {
49+ return [
50+ 'property name `color` maybe matching that of existing declaration ' => ['color ' ],
51+ 'property name `display` maybe matching that of existing declaration ' => ['display ' ],
52+ 'property name `width` not matching that of existing declaration ' => ['width ' ],
53+ ];
54+ }
55+
56+ /**
57+ * @return array<string, array{0: list<string>, 1: string}>
58+ */
59+ public static function provideInitialPropertyNamesAndPropertyNameToAdd ()
60+ {
61+ if (!\class_exists (DataProviders::class)) {
62+ self ::markTestSkipped ('`DataProviders` class is not available ' );
63+ return [];
64+ }
65+
66+ return DataProviders::cross (self ::providePropertyNamesToBeSetInitially (), self ::providePropertyNameToAdd ());
67+ }
68+
69+ /**
70+ * @test
71+ *
72+ * @param list<string> $initialPropertyNames
73+ *
74+ * @dataProvider provideInitialPropertyNamesAndPropertyNameToAdd
75+ */
76+ public function addRuleWithoutSiblingAddsRuleAfterInitialRulesAndSetsValidLineAndColumnNumbers (
77+ array $ initialPropertyNames ,
78+ string $ propertyNameToAdd
79+ ) {
80+ if ($ initialPropertyNames === []) {
81+ self ::markTestSkipped ('currently broken - first rule added does not have valid line number set ' );
82+ }
83+
84+ $ subject = new ConcreteRuleSet ();
85+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
86+ self ::setRulesFromPropertyNames ($ subject , $ initialPropertyNames );
87+
88+ $ subject ->addRule ($ ruleToAdd );
89+
90+ $ rules = $ subject ->getRules ();
91+ self ::assertSame ($ ruleToAdd , \end ($ rules ));
92+ self ::assertInternalType ('int ' , $ ruleToAdd ->getLineNumber (), 'line number not set ' );
93+ self ::assertGreaterThanOrEqual (1 , $ ruleToAdd ->getLineNumber (), 'line number not valid ' );
94+ self ::assertInternalType ('int ' , $ ruleToAdd ->getColumnNumber (), 'column number not set ' );
95+ self ::assertGreaterThanOrEqual (0 , $ ruleToAdd ->getColumnNumber (), 'column number not valid ' );
96+ }
97+
98+ /**
99+ * @test
100+ *
101+ * @dataProvider provideInitialPropertyNamesAndPropertyNameToAdd
102+ *
103+ * @param list<string> $initialPropertyNames
104+ */
105+ public function addRuleWithOnlyLineNumberAddsRuleAndSetsColumnNumberPreservingLineNumber (
106+ array $ initialPropertyNames ,
107+ string $ propertyNameToAdd
108+ ) {
109+ self ::markTestSkipped ('currently broken - does not set column number ' );
110+
111+ $ subject = new ConcreteRuleSet ();
112+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
113+ $ ruleToAdd ->setPosition (42 );
114+ self ::setRulesFromPropertyNames ($ subject , $ initialPropertyNames );
115+
116+ $ subject ->addRule ($ ruleToAdd );
117+
118+ self ::assertContains ($ ruleToAdd , $ subject ->getRules ());
119+ self ::assertInternalType ('int ' , $ ruleToAdd ->getColumnNumber (), 'column number not set ' );
120+ self ::assertGreaterThanOrEqual (0 , $ ruleToAdd ->getColumnNumber (), 'column number not valid ' );
121+ self ::assertSame (42 , $ ruleToAdd ->getLineNumber (), 'line number not preserved ' );
122+ }
123+
124+ /**
125+ * @test
126+ *
127+ * @dataProvider provideInitialPropertyNamesAndPropertyNameToAdd
128+ *
129+ * @param list<string> $initialPropertyNames
130+ */
131+ public function addRuleWithOnlyColumnNumberAddsRuleAndSetsLineNumberPreservingColumnNumber (
132+ array $ initialPropertyNames ,
133+ string $ propertyNameToAdd
134+ ) {
135+ self ::markTestSkipped ('currently broken - does not preserve column number ' );
136+
137+ $ subject = new ConcreteRuleSet ();
138+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
139+ $ ruleToAdd ->setPosition (null , 42 );
140+ self ::setRulesFromPropertyNames ($ subject , $ initialPropertyNames );
141+
142+ $ subject ->addRule ($ ruleToAdd );
143+
144+ self ::assertContains ($ ruleToAdd , $ subject ->getRules ());
145+ self ::assertInternalType ('int ' , $ ruleToAdd ->getLineNumber (), 'line number not set ' );
146+ self ::assertGreaterThanOrEqual (1 , $ ruleToAdd ->getLineNumber (), 'line number not valid ' );
147+ self ::assertSame (42 , $ ruleToAdd ->getColumnNumber (), 'column number not preserved ' );
148+ }
149+
150+ /**
151+ * @test
152+ *
153+ * @dataProvider provideInitialPropertyNamesAndPropertyNameToAdd
154+ *
155+ * @param list<string> $initialPropertyNames
156+ */
157+ public function addRuleWithCompletePositionAddsRuleAndPreservesPosition (
158+ array $ initialPropertyNames ,
159+ string $ propertyNameToAdd
160+ ) {
161+ $ subject = new ConcreteRuleSet ();
162+ $ ruleToAdd = new Rule ($ propertyNameToAdd );
163+ $ ruleToAdd ->setPosition (42 , 64 );
164+ self ::setRulesFromPropertyNames ($ subject , $ initialPropertyNames );
165+
166+ $ subject ->addRule ($ ruleToAdd );
167+
168+ self ::assertContains ($ ruleToAdd , $ subject ->getRules ());
169+ self ::assertSame (42 , $ ruleToAdd ->getLineNumber (), 'line number not preserved ' );
170+ self ::assertSame (64 , $ ruleToAdd ->getColumnNumber (), 'column number not preserved ' );
171+ }
172+
30173 /**
31174 * @return array<string, array{0: list<string>, 1: string, 2: list<string>}>
32175 */
@@ -171,25 +314,12 @@ public function removeMatchingRulesRemovesRulesByPropertyNamePrefixAndKeepsOther
171314 }
172315 }
173316
174- /**
175- * @return array<string, array{0: list<string>}>
176- */
177- public static function providePropertyNamesToRemove ()
178- {
179- return [
180- 'no properties ' => [[]],
181- 'one property ' => [['color ' ]],
182- 'two different properties ' => [['color ' , 'display ' ]],
183- 'two of the same property ' => [['color ' , 'color ' ]],
184- ];
185- }
186-
187317 /**
188318 * @test
189319 *
190320 * @param list<string> $propertyNamesToRemove
191321 *
192- * @dataProvider providePropertyNamesToRemove
322+ * @dataProvider providePropertyNamesToBeSetInitially
193323 */
194324 public function removeAllRulesRemovesAllRules (array $ propertyNamesToRemove )
195325 {
0 commit comments