1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Hyde \Framework \Testing \Unit ;
6+
7+ use Hyde \Facades \Config ;
8+ use Hyde \Facades \Filesystem ;
9+ use Hyde \Foundation \HydeKernel ;
10+ use Hyde \Framework \Actions \PreBuildTasks \TransferMediaAssets ;
11+ use Hyde \Framework \Features \BuildTasks \BuildTaskSkippedException ;
12+ use Hyde \Support \Filesystem \MediaFile ;
13+ use Hyde \Testing \UnitTestCase ;
14+ use Illuminate \Console \OutputStyle ;
15+ use Mockery ;
16+ use Symfony \Component \Console \Input \ArrayInput ;
17+ use Symfony \Component \Console \Output \BufferedOutput ;
18+
19+ /**
20+ * @covers \Hyde\Framework\Actions\PreBuildTasks\TransferMediaAssets
21+ */
22+ class TransferMediaAssetsUnitTest extends UnitTestCase
23+ {
24+ protected TransferMediaAssets $ task ;
25+
26+ protected function setUp (): void
27+ {
28+ parent ::setUp ();
29+
30+ $ this ->task = new TransferMediaAssets ();
31+ }
32+
33+ public function testItCanBeInstantiated ()
34+ {
35+ $ this ->assertInstanceOf (TransferMediaAssets::class, $ this ->task );
36+ }
37+
38+ public function testGetMessage ()
39+ {
40+ $ this ->assertSame ('Transferring Media Assets ' , $ this ->task ->getMessage ());
41+ }
42+
43+ public function testSkipsWhenNoMediaFiles ()
44+ {
45+ // Mock MediaFile::all to return empty collection
46+ HydeKernel::setInstance (Mockery::mock (new HydeKernel (), function ($ mock ) {
47+ $ mock ->shouldReceive ('assets ' )->once ()->andReturn (collect ());
48+ }));
49+
50+ $ this ->expectException (BuildTaskSkippedException::class);
51+ $ this ->expectExceptionMessage ("No media files to transfer. \n" );
52+
53+ $ this ->task ->handle ();
54+ }
55+
56+ public function testSkipsWhenOnlyAppCssAndUsingCdn ()
57+ {
58+ // Mock Config::getBool to return true for hyde.load_app_styles_from_cdn
59+ self ::mockConfig (['hyde.load_app_styles_from_cdn ' => true ]);
60+
61+ // Mock MediaFile::files to return only app.css
62+ HydeKernel::setInstance (Mockery::mock (new HydeKernel (), function ($ mock ) {
63+ $ mock ->shouldReceive ('assets ' )->once ()->andReturn (collect (['app.css ' => new MediaFile ('app.css ' )]));
64+ }));
65+
66+ $ this ->expectException (BuildTaskSkippedException::class);
67+ $ this ->expectExceptionMessage ("No media files to transfer. \n" );
68+
69+ $ this ->task ->handle ();
70+ }
71+
72+ public function testExcludesAppCssWhenUsingCdn ()
73+ {
74+ // Create a collection with multiple files including app.css
75+ $ mediaFiles = collect ([
76+ 'app.css ' => new MediaFile ('app.css ' ),
77+ 'style.css ' => new MediaFile ('style.css ' ),
78+ 'image.jpg ' => new MediaFile ('image.jpg ' )
79+ ]);
80+
81+ // The collection after forgetting app.css
82+ $ expectedFiles = collect ([
83+ 'style.css ' => new MediaFile ('style.css ' ),
84+ 'image.jpg ' => new MediaFile ('image.jpg ' )
85+ ]);
86+
87+ // Mock Config::getBool to return true for hyde.load_app_styles_from_cdn
88+ self ::mockConfig (['hyde.load_app_styles_from_cdn ' => true ]);
89+
90+ // Mock MediaFile::all to return our collection
91+ HydeKernel::setInstance (Mockery::mock (new HydeKernel (), function ($ mock ) use ($ mediaFiles ) {
92+ $ mock ->shouldReceive ('assets ' )->once ()->andReturn ($ mediaFiles );
93+ }));
94+
95+ // Mock methods on the task to prevent actual execution but verify correct flow
96+ $ taskMock = Mockery::mock (TransferMediaAssets::class)->makePartial ();
97+ $ taskMock ->shouldReceive ('withProgressBar ' )
98+ ->once ()
99+ ->with (Mockery::on (function ($ arg ) use ($ expectedFiles ) {
100+ // Verify app.css is not in the collection
101+ return !$ arg ->has ('app.css ' ) && $ arg ->count () === 2 ;
102+ }), Mockery::type ('Closure ' ))
103+ ->andReturn (null );
104+
105+ $ taskMock ->shouldReceive ('newLine ' )->twice ();
106+
107+ $ taskMock ->handle ();
108+ }
109+
110+ public function testTransfersMediaFiles ()
111+ {
112+ // Create a collection with media files
113+ $ file1 = new MediaFile ('style.css ' );
114+ $ file2 = new MediaFile ('image.jpg ' );
115+
116+ $ mediaFiles = collect ([
117+ 'style.css ' => $ file1 ,
118+ 'image.jpg ' => $ file2
119+ ]);
120+
121+ // Mock Config::getBool to return false for hyde.load_app_styles_from_cdn
122+ self ::mockConfig (['hyde.load_app_styles_from_cdn ' => false ]);
123+
124+ // Mock MediaFile::all to return our collection
125+ $ this ->mock (MediaFile::class, function ($ mock ) use ($ mediaFiles ) {
126+ $ mock ->shouldReceive ('all ' )->once ()->andReturn ($ mediaFiles );
127+ $ mock ->shouldReceive ('files ' )->never ();
128+ });
129+
130+ // Create a mock for the TransferMediaAssets class
131+ $ taskMock = Mockery::mock (TransferMediaAssets::class)->makePartial ();
132+
133+ // Mock withProgressBar to execute the callback for each file
134+ $ taskMock ->shouldReceive ('withProgressBar ' )
135+ ->once ()
136+ ->with (Mockery::type ('Illuminate\Support\Collection ' ), Mockery::type ('Closure ' ))
137+ ->andReturnUsing (function ($ files , $ callback ) {
138+ foreach ($ files as $ file ) {
139+ $ callback ($ file );
140+ }
141+ });
142+
143+ // Mock needsParentDirectory to prevent actual directory creation
144+ $ taskMock ->shouldReceive ('needsParentDirectory ' )->twice ();
145+
146+ // Mock Filesystem::putContents to verify it's called with the right parameters
147+ $ this ->mock (Filesystem::class, function ($ mock ) use ($ file1 , $ file2 ) {
148+ $ mock ->shouldReceive ('putContents ' )
149+ ->once ()
150+ ->with ($ file1 ->getOutputPath (), $ file1 ->getContents ());
151+
152+ $ mock ->shouldReceive ('putContents ' )
153+ ->once ()
154+ ->with ($ file2 ->getOutputPath (), $ file2 ->getContents ());
155+ });
156+
157+ $ taskMock ->shouldReceive ('newLine ' )->twice ();
158+
159+ $ taskMock ->handle ();
160+ }
161+
162+ public function testPrintFinishMessageDoesNothing ()
163+ {
164+ ob_start ();
165+ $ this ->task ->printFinishMessage ();
166+ $ output = ob_get_clean ();
167+
168+ $ this ->assertEmpty ($ output );
169+ }
170+
171+ public function testNeedsParentDirectoryCreatesDirectory ()
172+ {
173+ // Mock Filesystem::makeDirectory to verify it's called
174+ $ this ->mock (Filesystem::class, function ($ mock ) {
175+ $ mock ->shouldReceive ('makeDirectory ' )
176+ ->once ()
177+ ->with ('path/to ' , true );
178+ });
179+
180+ // Use reflection to call protected method
181+ $ method = new \ReflectionMethod (TransferMediaAssets::class, 'needsParentDirectory ' );
182+ $ method ->setAccessible (true );
183+ $ method ->invoke ($ this ->task , 'path/to/file.txt ' );
184+ }
185+ }
0 commit comments