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,324 @@ 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 ' => ['earl-grey: hot ' ],
311+ 'string with trailing semicolon ' => ['Earl Grey: hot; ' ],
312+ 'string with semicolon in the middle ' => ['Earl Grey: hot; Coffee: Americano ' ],
313+ 'string with semicolons in the middle and trailing ' => ['Earl Grey: hot; Coffee: Americano; ' ],
314+ ];
315+ }
316+
317+ /**
318+ * @test
319+ * @dataProvider provideUnchangedStringForRemoveLastSemicolon
320+ */
321+ public function removeLastSemicolonWithSemicolonAfterLastRuleEnabledReturnsUnchangedArgument (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 ' => ['Earl Grey: hot ' , 'Earl Grey: hot ' ],
338+ 'just 1 semicolon ' => ['; ' , '' ],
339+ 'just 2 semicolons ' => [';; ' , '; ' ],
340+ 'string with trailing semicolon ' => ['Earl Grey: hot; ' , 'Earl Grey: hot ' ],
341+ 'string with semicolon in the middle ' => [
342+ 'Earl Grey: hot; Coffee: Americano ' ,
343+ 'Earl Grey: hot Coffee: Americano ' ,
344+ ],
345+ 'string with semicolon in the middle and trailing ' => [
346+ 'Earl Grey: hot; Coffee: Americano; ' ,
347+ 'Earl Grey: hot; Coffee: Americano ' ,
348+ ],
349+ 'string with 2 semicolons in the middle ' => ['tea; coffee; Club-Mate ' , 'tea; coffee Club-Mate ' ],
350+ 'string with 2 semicolons in the middle surrounded by spaces ' => [
351+ 'Earl Grey: hot ; Coffee: Americano ; Club-Mate: cold ' ,
352+ 'Earl Grey: hot ; Coffee: Americano Club-Mate: cold ' ,
353+ ],
354+ 'string with 2 adjacent semicolons in the middle ' => [
355+ 'Earl Grey: hot;; Coffee: Americano ' ,
356+ 'Earl Grey: hot; Coffee: Americano ' ,
357+ ],
358+ 'string with 3 adjacent semicolons in the middle ' => [
359+ 'Earl Grey: hot;;; Coffee: Americano ' ,
360+ 'Earl Grey: hot;; Coffee: Americano ' ,
361+ ],
362+ ];
363+ }
364+
365+ /**
366+ * @test
367+ * @dataProvider provideChangedStringForRemoveLastSemicolon
368+ */
369+ public function removeLastSemicolonWithSemicolonAfterLastRuleDisabledRemovesLastSemicolon (
370+ string $ input ,
371+ string $ expected
372+ ): void {
373+ $ this ->outputFormat ->setSemicolonAfterLastRule (false );
374+
375+ $ result = $ this ->subject ->removeLastSemicolon ($ input );
376+
377+ self ::assertSame ($ expected , $ result );
378+ }
379+
380+ /**
381+ * @test
382+ */
383+ public function commentsWithEmptyCommentableAndRenderCommentsDisabledDoesNotReturnSpaceBetweenBlocks (): void
384+ {
385+ $ this ->outputFormat ->setRenderComments (false );
386+ $ spaceBetweenBlocks = ' between-space ' ;
387+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ spaceBetweenBlocks );
388+
389+ $ commentable = $ this ->createMock (Commentable::class);
390+ $ commentable ->method ('getComments ' )->willReturn ([]);
391+
392+ $ result = $ this ->subject ->comments ($ commentable );
393+
394+ self ::assertStringNotContainsString ($ spaceBetweenBlocks , $ result );
395+ }
396+
397+ /**
398+ * @test
399+ */
400+ public function commentsWithEmptyCommentableAndRenderCommentsDisabledDoesNotReturnSpaceAfterBlocks (): void
401+ {
402+ $ this ->outputFormat ->setRenderComments (false );
403+ $ spaceAfterBlocks = ' after-space ' ;
404+ $ this ->outputFormat ->setSpaceAfterBlocks ($ spaceAfterBlocks );
405+
406+ $ commentable = $ this ->createMock (Commentable::class);
407+ $ commentable ->method ('getComments ' )->willReturn ([]);
408+
409+ $ result = $ this ->subject ->comments ($ commentable );
410+
411+ self ::assertStringNotContainsString ($ spaceAfterBlocks , $ result );
412+ }
413+
414+ /**
415+ * @test
416+ */
417+ public function commentsWithEmptyCommentableAndRenderCommentsDisabledReturnsEmptyString (): void
418+ {
419+ $ this ->outputFormat ->setRenderComments (false );
420+
421+ $ commentable = $ this ->createMock (Commentable::class);
422+ $ commentable ->method ('getComments ' )->willReturn ([]);
423+
424+ $ result = $ this ->subject ->comments ($ commentable );
425+
426+ self ::assertSame ('' , $ result );
427+ }
428+
429+ /**
430+ * @test
431+ */
432+ public function commentsWithEmptyCommentableAndRenderCommentsEnabledDoesNotReturnSpaceBetweenBlocks (): void
433+ {
434+ $ this ->outputFormat ->setRenderComments (true );
435+ $ spaceBetweenBlocks = ' between-space ' ;
436+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ spaceBetweenBlocks );
437+
438+ $ commentable = $ this ->createMock (Commentable::class);
439+ $ commentable ->method ('getComments ' )->willReturn ([]);
440+
441+ $ result = $ this ->subject ->comments ($ commentable );
442+
443+ self ::assertStringNotContainsString ($ spaceBetweenBlocks , $ result );
444+ }
445+
446+ /**
447+ * @test
448+ */
449+ public function commentsWithEmptyCommentableAndRenderCommentsEnabledDoesNotReturnSpaceAfterBlocks (): void
450+ {
451+ $ this ->outputFormat ->setRenderComments (true );
452+ $ spaceAfterBlocks = ' after-space ' ;
453+ $ this ->outputFormat ->setSpaceAfterBlocks ($ spaceAfterBlocks );
454+
455+ $ commentable = $ this ->createMock (Commentable::class);
456+ $ commentable ->method ('getComments ' )->willReturn ([]);
457+
458+ $ result = $ this ->subject ->comments ($ commentable );
459+
460+ self ::assertStringNotContainsString ($ spaceAfterBlocks , $ result );
461+ }
462+
463+ /**
464+ * @test
465+ */
466+ public function commentsWithEmptyCommentableAndRenderCommentsEnabledReturnsEmptyString (): void
467+ {
468+ $ this ->outputFormat ->setRenderComments (true );
469+
470+ $ commentable = $ this ->createMock (Commentable::class);
471+ $ commentable ->method ('getComments ' )->willReturn ([]);
472+
473+ $ result = $ this ->subject ->comments ($ commentable );
474+
475+ self ::assertSame ('' , $ result );
476+ }
477+
478+ /**
479+ * @test
480+ */
481+ public function commentsWithCommentableWithOneCommentAndRenderCommentsDisabledReturnsEmptyString (): void
482+ {
483+ $ this ->outputFormat ->setRenderComments (false );
484+
485+ $ commentText = 'I am a teapot. ' ;
486+ $ comment = new Comment ($ commentText );
487+ $ commentable = $ this ->createMock (Commentable::class);
488+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
489+
490+ $ result = $ this ->subject ->comments ($ commentable );
491+
492+ self ::assertSame ('' , $ result );
493+ }
494+
495+ /**
496+ * @test
497+ */
498+ public function commentsWithCommentableWithOneCommentRendersComment (): void
499+ {
500+ $ this ->outputFormat ->setRenderComments (true );
501+
502+ $ commentText = 'I am a teapot. ' ;
503+ $ comment = new Comment ($ commentText );
504+ $ commentable = $ this ->createMock (Commentable::class);
505+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
506+
507+ $ result = $ this ->subject ->comments ($ commentable );
508+
509+ self ::assertStringContainsString ('/* ' . $ commentText . '*/ ' , $ result );
510+ }
511+
512+ /**
513+ * @test
514+ */
515+ public function commentsWithCommentableWithOneCommentPutsSpaceAfterBlocksAfterRenderedComment (): void
516+ {
517+ $ this ->outputFormat ->setRenderComments (true );
518+ $ afterSpace = ' after-space ' ;
519+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
520+
521+ $ commentText = 'I am a teapot. ' ;
522+ $ comment = new Comment ($ commentText );
523+ $ commentable = $ this ->createMock (Commentable::class);
524+ $ commentable ->method ('getComments ' )->willReturn ([$ comment ]);
525+
526+ $ result = $ this ->subject ->comments ($ commentable );
527+
528+ self ::assertSame ('/* ' . $ commentText . '*/ ' . $ afterSpace , $ result );
529+ }
530+
531+ /**
532+ * @test
533+ */
534+ public function commentsWithCommentableWithTwoCommentsPutsSpaceAfterBlocksAfterLastRenderedComment (): void
535+ {
536+ $ this ->outputFormat ->setRenderComments (true );
537+ $ afterSpace = ' after-space ' ;
538+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
539+
540+ $ commentText1 = 'I am a teapot. ' ;
541+ $ comment1 = new Comment ($ commentText1 );
542+ $ commentText2 = 'But I am not. ' ;
543+ $ comment2 = new Comment ($ commentText2 );
544+ $ commentable = $ this ->createMock (Commentable::class);
545+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 ]);
546+
547+ $ result = $ this ->subject ->comments ($ commentable );
548+
549+ self ::assertStringContainsString ('/* ' . $ commentText2 . '*/ ' . $ afterSpace , $ result );
550+ }
551+
552+ /**
553+ * @test
554+ */
555+ public function commentsWithCommentableWithTwoCommentsSeparatesCommentsBySpaceBetweenBlocks (): void
556+ {
557+ $ this ->outputFormat ->setRenderComments (true );
558+ $ betweenSpace = ' between-space ' ;
559+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ betweenSpace );
560+
561+ $ commentText1 = 'I am a teapot. ' ;
562+ $ comment1 = new Comment ($ commentText1 );
563+ $ commentText2 = 'But I am not. ' ;
564+ $ comment2 = new Comment ($ commentText2 );
565+ $ commentable = $ this ->createMock (Commentable::class);
566+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 ]);
567+
568+ $ result = $ this ->subject ->comments ($ commentable );
569+
570+ $ expected = '/* ' . $ commentText1 . '*/ ' . $ betweenSpace . '/* ' . $ commentText2 . '*/ ' ;
571+ self ::assertStringContainsString ($ expected , $ result );
572+ }
573+
574+ /**
575+ * @test
576+ */
577+ public function commentsWithCommentableWithMoreThanTwoCommentsPutsSpaceAfterBlocksAfterLastRenderedComment (): void
578+ {
579+ $ this ->outputFormat ->setRenderComments (true );
580+ $ afterSpace = ' after-space ' ;
581+ $ this ->outputFormat ->setSpaceAfterBlocks ($ afterSpace );
582+
583+ $ commentText1 = 'I am a teapot. ' ;
584+ $ comment1 = new Comment ($ commentText1 );
585+ $ commentText2 = 'But I am not. ' ;
586+ $ comment2 = new Comment ($ commentText2 );
587+ $ commentText3 = 'So what am I then? ' ;
588+ $ comment3 = new Comment ($ commentText3 );
589+ $ commentable = $ this ->createMock (Commentable::class);
590+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 , $ comment3 ]);
591+
592+ $ result = $ this ->subject ->comments ($ commentable );
593+
594+ self ::assertStringContainsString ('/* ' . $ commentText3 . '*/ ' . $ afterSpace , $ result );
595+ }
596+
597+ /**
598+ * @test
599+ */
600+ public function commentsWithCommentableWithMoreThanTwoCommentsSeparatesCommentsBySpaceBetweenBlocks (): void
601+ {
602+ $ this ->outputFormat ->setRenderComments (true );
603+ $ betweenSpace = ' between-space ' ;
604+ $ this ->outputFormat ->setSpaceBetweenBlocks ($ betweenSpace );
605+
606+ $ commentText1 = 'I am a teapot. ' ;
607+ $ comment1 = new Comment ($ commentText1 );
608+ $ commentText2 = 'But I am not. ' ;
609+ $ comment2 = new Comment ($ commentText2 );
610+ $ commentText3 = 'So what am I then? ' ;
611+ $ comment3 = new Comment ($ commentText3 );
612+ $ commentable = $ this ->createMock (Commentable::class);
613+ $ commentable ->method ('getComments ' )->willReturn ([$ comment1 , $ comment2 , $ comment3 ]);
614+
615+ $ result = $ this ->subject ->comments ($ commentable );
616+
617+ $ expected = '/* ' . $ commentText1 . '*/ '
618+ . $ betweenSpace . '/* ' . $ commentText2 . '*/ '
619+ . $ betweenSpace . '/* ' . $ commentText3 . '*/ ' ;
620+ self ::assertStringContainsString ($ expected , $ result );
621+ }
300622}
0 commit comments