Skip to content

Commit 5ec4ae8

Browse files
committed
test: add unit tests for AssetQueue functionality
1 parent 1ac1d6d commit 5ec4ae8

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed

psalm.baseline.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,12 @@
883883
<code><![CDATA[$slug]]></code>
884884
</PossiblyUnusedProperty>
885885
</file>
886+
<file src="tests/unit/AssetQueueTest.php">
887+
<PossiblyUndefinedIntArrayOffset>
888+
<code><![CDATA[$existingAssets[1]]]></code>
889+
<code><![CDATA[$processedAssets[0]]]></code>
890+
</PossiblyUndefinedIntArrayOffset>
891+
</file>
886892
<file src="web/index.php">
887893
<MixedArgument>
888894
<code><![CDATA[$GLOBALS['YASSG_BASEDIR'] ?? throw new LogicException('YASSG base dir not found')]]></code>

tests/unit/AssetQueueTest.php

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Sigwin Yassg project.
7+
*
8+
* (c) sigwin.hr
9+
*
10+
* This source file is subject to the MIT license that is bundled
11+
* with this source code in the file LICENSE.
12+
*/
13+
14+
namespace Sigwin\YASSG\Test;
15+
16+
use PHPUnit\Framework\TestCase;
17+
use Sigwin\YASSG\Asset\AssetCopy;
18+
use Sigwin\YASSG\Asset\AssetFetch;
19+
use Sigwin\YASSG\AssetQueue;
20+
use Symfony\Component\Filesystem\Filesystem;
21+
use Symfony\Contracts\HttpClient\HttpClientInterface;
22+
23+
/**
24+
* @internal
25+
*
26+
* @small
27+
*/
28+
#[\PHPUnit\Framework\Attributes\CoversClass(AssetQueue::class)]
29+
#[\PHPUnit\Framework\Attributes\UsesClass(AssetCopy::class)]
30+
#[\PHPUnit\Framework\Attributes\UsesClass(AssetFetch::class)]
31+
final class AssetQueueTest extends TestCase
32+
{
33+
private string $tempDir;
34+
private AssetQueue $assetQueue;
35+
private Filesystem $filesystem;
36+
private HttpClientInterface $httpClient;
37+
38+
#[\Override]
39+
protected function setUp(): void
40+
{
41+
$this->tempDir = sys_get_temp_dir().'/yassg_test_'.uniqid();
42+
mkdir($this->tempDir, 0777, true);
43+
44+
$this->filesystem = new Filesystem();
45+
$this->httpClient = $this->createMock(HttpClientInterface::class);
46+
$this->assetQueue = new AssetQueue($this->tempDir, $this->filesystem, $this->httpClient);
47+
}
48+
49+
#[\Override]
50+
protected function tearDown(): void
51+
{
52+
if (is_dir($this->tempDir)) {
53+
$this->filesystem->remove($this->tempDir);
54+
}
55+
}
56+
57+
public function testFlushReturnsAllAssetsIncludingExisting(): void
58+
{
59+
// Create a temporary source file
60+
$sourceFile = $this->tempDir.'/source.txt';
61+
file_put_contents($sourceFile, 'test content');
62+
63+
// Create existing destination file
64+
$existingDestination = '/existing/asset.txt';
65+
$existingDestinationPath = $this->tempDir.$existingDestination;
66+
$this->filesystem->mkdir(\dirname($existingDestinationPath));
67+
file_put_contents($existingDestinationPath, 'existing content');
68+
69+
// Create new destination path (doesn't exist yet)
70+
$newDestination = '/new/asset.txt';
71+
72+
// Add assets to queue
73+
$existingAsset = new AssetCopy($sourceFile, $existingDestination);
74+
$newAsset = new AssetCopy($sourceFile, $newDestination);
75+
76+
$this->assetQueue->add($existingAsset);
77+
$this->assetQueue->add($newAsset);
78+
79+
// Track which assets were processed via callback
80+
$processedAssets = [];
81+
82+
// Flush the queue
83+
$returnedAssets = $this->assetQueue->flush(static function ($asset) use (&$processedAssets): void {
84+
$processedAssets[] = $asset;
85+
});
86+
87+
/**
88+
* Added for mutation tests.
89+
*
90+
* @psalm-suppress RedundantCondition
91+
*
92+
* @phpstan-ignore-next-line
93+
*/
94+
self::assertTrue(array_is_list($returnedAssets), 'Returned assets should be a list');
95+
96+
// Should return ALL assets (both existing and new) for incremental build support
97+
self::assertCount(2, $returnedAssets, 'Should return all assets including existing ones');
98+
self::assertContains($existingAsset, $returnedAssets, 'Should include existing asset in return');
99+
self::assertContains($newAsset, $returnedAssets, 'Should include new asset in return');
100+
101+
// Verify callback was only called for new asset (existing assets are skipped from processing)
102+
self::assertCount(1, $processedAssets, 'Callback should only be called for newly processed assets');
103+
self::assertSame($newAsset, $processedAssets[0], 'Callback should be called with the new asset only');
104+
105+
// Verify the new asset was actually copied
106+
self::assertFileExists($this->tempDir.$newDestination, 'New asset should be copied');
107+
self::assertSame('test content', file_get_contents($this->tempDir.$newDestination));
108+
109+
// Verify existing file was not modified
110+
self::assertSame('existing content', file_get_contents($existingDestinationPath));
111+
}
112+
113+
public function testFlushWithNoExistingAssets(): void
114+
{
115+
// Create a temporary source file
116+
$sourceFile = $this->tempDir.'/source.txt';
117+
file_put_contents($sourceFile, 'test content');
118+
119+
// Create assets that don't exist yet
120+
$asset1 = new AssetCopy($sourceFile, '/new/asset1.txt');
121+
$asset2 = new AssetCopy($sourceFile, '/new/asset2.txt');
122+
123+
$this->assetQueue->add($asset1);
124+
$this->assetQueue->add($asset2);
125+
126+
// Track which assets were processed via callback
127+
$processedAssets = [];
128+
129+
// Flush the queue
130+
$returnedAssets = $this->assetQueue->flush(static function ($asset) use (&$processedAssets): void {
131+
$processedAssets[] = $asset;
132+
});
133+
134+
// Should return all assets since none existed
135+
self::assertCount(2, $returnedAssets, 'Should return all processed assets');
136+
self::assertContains($asset1, $returnedAssets);
137+
self::assertContains($asset2, $returnedAssets);
138+
139+
// Verify callback was called for all assets
140+
self::assertCount(2, $processedAssets, 'Callback should be called for all processed assets');
141+
self::assertContains($asset1, $processedAssets);
142+
self::assertContains($asset2, $processedAssets);
143+
144+
// Verify both assets were copied
145+
self::assertFileExists($this->tempDir.'/new/asset1.txt');
146+
self::assertFileExists($this->tempDir.'/new/asset2.txt');
147+
}
148+
149+
public function testFlushWithAllExistingAssets(): void
150+
{
151+
// Create a temporary source file
152+
$sourceFile = $this->tempDir.'/source.txt';
153+
file_put_contents($sourceFile, 'test content');
154+
155+
// Create multiple existing destination files
156+
$existingDestinations = ['/existing1/asset.txt', '/existing2/asset.txt'];
157+
$existingAssets = [];
158+
159+
foreach ($existingDestinations as $destination) {
160+
$path = $this->tempDir.$destination;
161+
$this->filesystem->mkdir(\dirname($path));
162+
file_put_contents($path, 'existing content');
163+
164+
$asset = new AssetCopy($sourceFile, $destination);
165+
$existingAssets[] = $asset;
166+
$this->assetQueue->add($asset);
167+
}
168+
169+
// Track which assets were processed via callback
170+
$processedAssets = [];
171+
172+
// Flush the queue
173+
$returnedAssets = $this->assetQueue->flush(static function ($asset) use (&$processedAssets): void {
174+
$processedAssets[] = $asset;
175+
});
176+
177+
// Should return all assets even though they all exist (for incremental build support)
178+
self::assertCount(2, $returnedAssets, 'Should return all assets even when they all exist');
179+
self::assertContains($existingAssets[0], $returnedAssets);
180+
self::assertContains($existingAssets[1], $returnedAssets);
181+
182+
// Verify callback was never called since no assets were actually processed
183+
self::assertEmpty($processedAssets, 'Callback should not be called when all assets already exist');
184+
185+
// Verify all existing files were not modified
186+
foreach ($existingDestinations as $destination) {
187+
$path = $this->tempDir.$destination;
188+
self::assertSame('existing content', file_get_contents($path));
189+
}
190+
}
191+
192+
public function testEmptyQueue(): void
193+
{
194+
$returnedAssets = $this->assetQueue->flush();
195+
196+
self::assertEmpty($returnedAssets, 'Empty queue should return empty array');
197+
}
198+
}

0 commit comments

Comments
 (0)