55namespace Sabberworm \CSS \Tests \Unit \RuleSet ;
66
77use PHPUnit \Framework \TestCase ;
8+ use Sabberworm \CSS \Comment \Comment ;
89use Sabberworm \CSS \CSSElement ;
910use Sabberworm \CSS \CSSList \CSSListItem ;
1011use Sabberworm \CSS \Parsing \ParserState ;
@@ -158,21 +159,85 @@ public function parsesTwoCommaSeparatedSelectors(string $firstSelector, string $
158159 self ::assertSame ([$ firstSelector , $ secondSelector ], self ::getSelectorsAsStrings ($ subject ));
159160 }
160161
162+ /**
163+ * @return array<non-empty-string, array{0: non-empty-string, 1: non-empty-string}>
164+ */
165+ public static function provideSelectorWithAndWithoutComment (): array
166+ {
167+ return [
168+ 'comment before ' => ['/*comment*/body ' , 'body ' ],
169+ 'comment after ' => ['body/*comment*/ ' , 'body ' ],
170+ 'comment within ' => ['./*comment*/teapot ' , '.teapot ' ],
171+ 'comment within function ' => [':not(#your-mug,/*comment*/.their-mug) ' , ':not(#your-mug,.their-mug) ' ],
172+ ];
173+ }
174+
175+ /**
176+ * @test
177+ *
178+ * @param non-empty-string $selectorWith
179+ * @param non-empty-string $selectorWithout
180+ *
181+ * @dataProvider provideSelectorWithAndWithoutComment
182+ */
183+ public function parsesSelectorWithComment (string $ selectorWith , string $ selectorWithout ): void
184+ {
185+ $ subject = DeclarationBlock::parse (new ParserState ($ selectorWith . ' {} ' , Settings::create ()));
186+
187+ self ::assertInstanceOf (DeclarationBlock::class, $ subject );
188+ self ::assertSame ([$ selectorWithout ], self ::getSelectorsAsStrings ($ subject ));
189+ }
190+
191+ /**
192+ * @test
193+ *
194+ * @param non-empty-string $selector
195+ *
196+ * @dataProvider provideSelectorWithAndWithoutComment
197+ */
198+ public function parseExtractsCommentFromSelector (string $ selector ): void
199+ {
200+ $ subject = DeclarationBlock::parse (new ParserState ($ selector . ' {} ' , Settings::create ()));
201+
202+ self ::assertInstanceOf (DeclarationBlock::class, $ subject );
203+ self ::assertSame (['comment ' ], self ::getCommentsAsStrings ($ subject ));
204+ }
205+
206+ /**
207+ * @test
208+ */
209+ public function parsesSelectorWithTwoComments (): void
210+ {
211+ $ subject = DeclarationBlock::parse (new ParserState ('/*comment1*/a/*comment2*/ {} ' , Settings::create ()));
212+
213+ self ::assertInstanceOf (DeclarationBlock::class, $ subject );
214+ self ::assertSame (['a ' ], self ::getSelectorsAsStrings ($ subject ));
215+ }
216+
217+ /**
218+ * @test
219+ */
220+ public function parseExtractsTwoCommentsFromSelector (): void
221+ {
222+ $ subject = DeclarationBlock::parse (new ParserState ('/*comment1*/a/*comment2*/ {} ' , Settings::create ()));
223+
224+ self ::assertInstanceOf (DeclarationBlock::class, $ subject );
225+ self ::assertSame (['comment1 ' , 'comment2 ' ], self ::getCommentsAsStrings ($ subject ));
226+ }
227+
161228 /**
162229 * @return array<non-empty-string, array{0: string, 1: non-empty-string}>
163230 */
164231 public static function provideInvalidSelectorAndExpectedExceptionMessage (): array
165232 {
166- // TODO: the `parse` method consumes the first character without inspection,
167- // so some of the test strings are prefixed with a space.
168233 return [
169- 'no selector ' => [' ' , 'Token “selector” (literal) not found. Got “{”. [line no: 1] ' ],
170- 'lone `(` ' => [' ( ' , 'Token “)” (literal) not found. Got “{”. ' ],
171- 'lone `)` ' => [' ) ' , 'Token “anything but” (literal) not found. Got “)”. ' ],
172- 'lone `,` ' => [' , ' , 'Token “selector” (literal) not found. Got “,”. [line no: 1] ' ],
234+ 'no selector ' => ['' , 'Token “selector” (literal) not found. Got “{”. [line no: 1] ' ],
235+ 'lone `(` ' => ['( ' , 'Token “)” (literal) not found. Got “{”. ' ],
236+ 'lone `)` ' => [') ' , 'Token “anything but” (literal) not found. Got “)”. ' ],
237+ 'lone `,` ' => [', ' , 'Token “selector” (literal) not found. Got “,”. [line no: 1] ' ],
173238 'unclosed `(` ' => [':not(#your-mug ' , 'Token “)” (literal) not found. Got “{”. ' ],
174239 'extra `)` ' => [':not(#your-mug)) ' , 'Token “anything but” (literal) not found. Got “)”. ' ],
175- '`,` missing left operand ' => [' , a ' , 'Token “selector” (literal) not found. Got “,”. [line no: 1] ' ],
240+ '`,` missing left operand ' => [', a ' , 'Token “selector” (literal) not found. Got “,”. [line no: 1] ' ],
176241 '`,` missing right operand ' => ['a, ' , 'Token “selector” (literal) not found. Got “{”. [line no: 1] ' ],
177242 ];
178243 }
@@ -199,8 +264,6 @@ static function (array $testData): array {
199264 /**
200265 * @test
201266 *
202- * @param non-empty-string $selector
203- *
204267 * @dataProvider provideInvalidSelector
205268 */
206269 public function parseSkipsBlockWithInvalidSelector (string $ selector ): void
@@ -326,6 +389,19 @@ static function (Selector $selectorObject): string {
326389 );
327390 }
328391
392+ /**
393+ * @return list<string>
394+ */
395+ private static function getCommentsAsStrings (DeclarationBlock $ declarationBlock ): array
396+ {
397+ return \array_map (
398+ static function (Comment $ comment ): string {
399+ return $ comment ->getComment ();
400+ },
401+ $ declarationBlock ->getComments ()
402+ );
403+ }
404+
329405 /**
330406 * @test
331407 */
0 commit comments