55namespace Sabberworm \CSS \Tests \Unit ;
66
77use PHPUnit \Framework \TestCase ;
8+ use Sabberworm \CSS \Comment \Comment ;
9+ use Sabberworm \CSS \Comment \Commentable ;
810use Sabberworm \CSS \OutputFormat ;
911use Sabberworm \CSS \OutputFormatter ;
1012use Sabberworm \CSS \Renderable ;
@@ -146,8 +148,8 @@ public function spaceBeforeListArgumentSeparatorReturnsSpaceSetForSpecificSepara
146148 /**
147149 * @test
148150 */
149- public function spaceBeforeListArgumentSeparatorWithoutSpecificSettingReturnsDefaultSpace (
150- ): void {
151+ public function spaceBeforeListArgumentSeparatorWithoutSpecificSettingReturnsDefaultSpace (): void
152+ {
151153 $ space = ' ' ;
152154 $ this ->outputFormat ->setSpaceBeforeListArgumentSeparators ([', ' => $ space ]);
153155 $ defaultSpace = "\t\t\t\t" ;
@@ -173,8 +175,8 @@ public function spaceAfterListArgumentSeparatorReturnsSpaceSetForSpecificSeparat
173175 /**
174176 * @test
175177 */
176- public function spaceAfterListArgumentSeparatorWithoutSpecificSettingReturnsDefaultSpace (
177- ): void {
178+ public function spaceAfterListArgumentSeparatorWithoutSpecificSettingReturnsDefaultSpace (): void
179+ {
178180 $ space = ' ' ;
179181 $ this ->outputFormat ->setSpaceAfterListArgumentSeparators ([', ' => $ space ]);
180182 $ defaultSpace = "\t\t\t\t" ;
@@ -297,4 +299,257 @@ public function implodeWithIncreaseLevelTrueIncreasesIndentationLevelForRenderin
297299
298300 self ::assertSame ($ renderedRenderable , $ result );
299301 }
302+
303+ /**
304+ * @return array<string, array{0: string}>
305+ */
306+ public function provideUnchangedStringForRemoveLastSemicolon (): array
307+ {
308+ return [
309+ 'empty string ' => ['' ],
310+ 'string without semicolon ' => ['Tea or coffee? ' ],
311+ 'string with trailing semicolon ' => ['Tea or coffee; ' ],
312+ 'string with semicolon in the middle ' => ['Tea; coffee ' ],
313+ 'string with semicolons in the middle and trailing ' => ['Tea; coffee; ' ],
314+ ];
315+ }
316+
317+ /**
318+ * @test
319+ * @dataProvider provideUnchangedStringForRemoveLastSemicolon
320+ */
321+ public function removeLastSemicolonWithSemicolonAfterLastRuleEnabledUnchangedArgument (string $ string ): void
322+ {
323+ $ this ->outputFormat ->setSemicolonAfterLastRule (true );
324+
325+ $ result = $ this ->subject ->removeLastSemicolon ($ string );
326+
327+ self ::assertSame ($ string , $ result );
328+ }
329+
330+ /**
331+ * @return array<string, array{0: string, 1: string}>
332+ */
333+ public function provideChangedStringForRemoveLastSemicolon (): array
334+ {
335+ return [
336+ 'empty string ' => ['' , '' ],
337+ 'non-empty string without semicolon ' => ['Tea or coffee? ' , 'Tea or coffee? ' ],
338+ 'just 1 semicolon ' => ['; ' , '' ],
339+ 'just 2 semicolons ' => [';; ' , '; ' ],
340+ 'string with trailing semicolon ' => ['tea or coffee; ' , 'tea or coffee ' ],
341+ 'string with semicolon in the middle ' => ['tea; coffee ' , 'tea coffee ' ],
342+ 'string with semicolon in the middle and trailing ' => ['tea; coffee; ' , 'tea; coffee ' ],
343+ 'string with 2 semicolons in the middle ' => ['tea; coffee; Club-Mate ' , 'tea; coffee Club-Mate ' ],
344+ 'string with 2 semicolons in the middle surrounded by spaces ' => [
345+ 'tea ; coffee ; Club-Mate ' ,
346+ 'tea ; coffee Club-Mate ' ,
347+ ],
348+ 'string with 2 adjacent semicolons in the middle ' => ['tea ;; coffee ' , 'tea ; coffee ' ],
349+ 'string with 3 adjacent semicolons in the middle ' => ['tea ;;; coffee ' , 'tea ;; coffee ' ],
350+ ];
351+ }
352+
353+ /**
354+ * @test
355+ * @dataProvider provideChangedStringForRemoveLastSemicolon
356+ */
357+ public function removeLastSemicolonWithSemicolonAfterLastRuleDisabledRemovesTheLastSemicolon (
358+ string $ input ,
359+ string $ expected
360+ ): void {
361+ $ this ->outputFormat ->setSemicolonAfterLastRule (false );
362+
363+ $ result = $ this ->subject ->removeLastSemicolon ($ input );
364+
365+ self ::assertSame ($ expected , $ result );
366+ }
367+
368+ /**
369+ * @test
370+ */
371+ public function commentsWithEmptyCommentableAndRenderCommentsDisabledReturnsEmptyString (): void
372+ {
373+ $ this ->outputFormat ->setRenderComments (false );
374+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
375+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
376+
377+ $ commentable = $ this ->createMock (Commentable::class);
378+ $ commentable ->method ('getComments ' )->willReturn ([]);
379+
380+ $ result = $ this ->subject ->comments ($ commentable );
381+
382+ self ::assertSame ('' , $ result );
383+ }
384+
385+ /**
386+ * @test
387+ */
388+ public function commentsWithEmptyCommentableAndRenderCommentsEnabledReturnsEmptyString (): void
389+ {
390+ $ this ->outputFormat ->setRenderComments (true );
391+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
392+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
393+
394+ $ commentable = $ this ->createMock (Commentable::class);
395+ $ commentable ->method ('getComments ' )->willReturn ([]);
396+
397+ $ result = $ this ->subject ->comments ($ commentable );
398+
399+ self ::assertSame ('' , $ result );
400+ }
401+
402+ /**
403+ * @test
404+ */
405+ public function commentsWithCommentableWithOneCommentAndRenderCommentsDisabledReturnsEmptyString (): void
406+ {
407+ $ this ->outputFormat ->setRenderComments (false );
408+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
409+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
410+
411+ $ commentText = 'This is a comment. ' ;
412+ $ comment = new Comment ($ commentText );
413+ $ commentable = $ this ->createMock (Commentable::class);
414+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
415+
416+ $ result = $ this ->subject ->comments ($ commentable );
417+
418+ self ::assertSame ('' , $ result );
419+ }
420+
421+ /**
422+ * @test
423+ */
424+ public function commentsWithCommentableWithOneCommentRendersComment (): void
425+ {
426+ $ this ->outputFormat ->setRenderComments (true );
427+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
428+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
429+
430+ $ commentText = 'This is a comment. ' ;
431+ $ comment = new Comment ($ commentText );
432+ $ commentable = $ this ->createMock (Commentable::class);
433+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
434+
435+ $ result = $ this ->subject ->comments ($ commentable );
436+
437+ self ::assertStringContainsString ('/* ' . $ commentText . '*/ ' , $ result );
438+ }
439+
440+ /**
441+ * @test
442+ */
443+ public function commentsWithCommentableWithOneCommentPutsSpaceAfterBlocksAfterRenderedComment (): void
444+ {
445+ $ this ->outputFormat ->setRenderComments (true );
446+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
447+ $ afterSpace = ' after-space ' ;
448+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
449+
450+ $ commentText = 'This is a comment. ' ;
451+ $ comment = new Comment ($ commentText );
452+ $ commentable = $ this ->createMock (Commentable::class);
453+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
454+
455+ $ result = $ this ->subject ->comments ($ commentable );
456+
457+ self ::assertSame ('/* ' . $ commentText . '*/ ' . $ afterSpace , $ result );
458+ }
459+
460+ /**
461+ * @test
462+ */
463+ public function commentsWithCommentableWithTwoCommentsPutsSpaceAfterBlocksAfterLastRenderedComment (): void
464+ {
465+ $ this ->outputFormat ->setRenderComments (true );
466+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
467+ $ afterSpace = ' after-space ' ;
468+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
469+
470+ $ commentText1 = 'This is a comment 1. ' ;
471+ $ comment1 = new Comment ($ commentText1 );
472+ $ commentText2 = 'This is a comment 2. ' ;
473+ $ comment2 = new Comment ($ commentText2 );
474+ $ commentable = $ this ->createMock (Commentable::class);
475+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 ]);
476+
477+ $ result = $ this ->subject ->comments ($ commentable );
478+
479+ self ::assertStringContainsString ('/* ' . $ commentText2 . '*/ ' . $ afterSpace , $ result );
480+ }
481+
482+ /**
483+ * @test
484+ */
485+ public function commentsWithCommentableWithTwoCommentsSeparatesCommentsBySpaceBetweenBlocks (): void
486+ {
487+ $ this ->outputFormat ->setRenderComments (true );
488+ $ betweenSpace = ' between-space ' ;
489+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ betweenSpace );
490+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
491+
492+ $ commentText1 = 'This is a comment 1. ' ;
493+ $ comment1 = new Comment ($ commentText1 );
494+ $ commentText2 = 'This is a comment 2. ' ;
495+ $ comment2 = new Comment ($ commentText2 );
496+ $ commentable = $ this ->createMock (Commentable::class);
497+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 ]);
498+
499+ $ result = $ this ->subject ->comments ($ commentable );
500+
501+ $ expected = '/* ' . $ commentText1 . '*/ ' . $ betweenSpace . '/* ' . $ commentText2 . '*/ ' ;
502+ self ::assertStringContainsString ($ expected , $ result );
503+ }
504+
505+ /**
506+ * @test
507+ */
508+ public function commentsWithCommentableWithMoreThanTwoCommentsPutsSpaceAfterBlocksAfterLastRenderedComment (): void
509+ {
510+ $ this ->outputFormat ->setRenderComments (true );
511+ $ this ->outputFormat ->setSpaceBetweenBlocks (' between-space ' );
512+ $ afterSpace = ' after-space ' ;
513+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
514+
515+ $ commentText1 = 'This is a comment 1. ' ;
516+ $ comment1 = new Comment ($ commentText1 );
517+ $ commentText2 = 'This is a comment 2. ' ;
518+ $ comment2 = new Comment ($ commentText2 );
519+ $ commentText3 = 'This is a comment 3. ' ;
520+ $ comment3 = new Comment ($ commentText3 );
521+ $ commentable = $ this ->createMock (Commentable::class);
522+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 , $ comment3 ]);
523+
524+ $ result = $ this ->subject ->comments ($ commentable );
525+
526+ self ::assertStringContainsString ('/* ' . $ commentText3 . '*/ ' . $ afterSpace , $ result );
527+ }
528+
529+ /**
530+ * @test
531+ */
532+ public function commentsWithCommentableWithMoreThanTwoCommentsSeparatesCommentsBySpaceBetweenBlocks (): void
533+ {
534+ $ this ->outputFormat ->setRenderComments (true );
535+ $ betweenSpace = ' between-space ' ;
536+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ betweenSpace );
537+ $ this ->outputFormat ->setSpaceAfterBlocks (' after-space ' );
538+
539+ $ commentText1 = 'This is a comment 1. ' ;
540+ $ comment1 = new Comment ($ commentText1 );
541+ $ commentText2 = 'This is a comment 2. ' ;
542+ $ comment2 = new Comment ($ commentText2 );
543+ $ commentText3 = 'This is a comment 3. ' ;
544+ $ comment3 = new Comment ($ commentText3 );
545+ $ commentable = $ this ->createMock (Commentable::class);
546+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 , $ comment3 ]);
547+
548+ $ result = $ this ->subject ->comments ($ commentable );
549+
550+ $ expected = '/* ' . $ commentText1 . '*/ '
551+ . $ betweenSpace . '/* ' . $ commentText2 . '*/ '
552+ . $ betweenSpace . '/* ' . $ commentText3 . '*/ ' ;
553+ self ::assertStringContainsString ($ expected , $ result );
554+ }
300555}
0 commit comments