Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalize the asset service #1186

Merged
merged 47 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
bd08562
Extract unit test
caendesilva Mar 2, 2023
beb2559
Convert test method names to camelCase
caendesilva Mar 2, 2023
b808729
Apply fixes from StyleCI
StyleCIBot Mar 2, 2023
14d9e9b
Refactor to move tests to unit test
caendesilva Mar 2, 2023
75cefaa
Extract constant for the default HydeFront version
caendesilva Mar 2, 2023
f515245
Clean up unit test
caendesilva Mar 2, 2023
ce8ec36
Improve unit test specificity
caendesilva Mar 2, 2023
11ae55d
Replace ?? with if
caendesilva Mar 2, 2023
2bbde3c
Convert concatenation to 'sprintf()' call
caendesilva Mar 2, 2023
c4bf992
Convert sprintf call to string replacement
caendesilva Mar 2, 2023
7a3e411
Split comma-separated values into multiple lines
caendesilva Mar 2, 2023
7a20ed3
Merge conditionals so custom path can use string replacement
caendesilva Mar 2, 2023
ba2adb7
Normalize test method names
caendesilva Mar 2, 2023
7bee425
Extract public constant for the CDN pattern
caendesilva Mar 2, 2023
c011e8e
Use assertSame
caendesilva Mar 2, 2023
d5f3d61
Set default config value to the constant
caendesilva Mar 2, 2023
923f643
Set default config value to the constant
caendesilva Mar 2, 2023
d7f0838
Rename constant
caendesilva Mar 2, 2023
7c2b65c
Add more documentation to the constants
caendesilva Mar 2, 2023
aa4546f
Update config files to match
caendesilva Mar 2, 2023
9b494d4
Set default property value to the constant
caendesilva Mar 2, 2023
2b8eeb7
Protected property $hydefrontUrl is no longer nullable
caendesilva Mar 2, 2023
605a29f
Use the strongly typed config facade
caendesilva Mar 2, 2023
df97da7
Use the strongly typed config facade
caendesilva Mar 2, 2023
3c2ee4e
Replace conditional configuration assignments with default values
caendesilva Mar 2, 2023
e609635
Remove newline
caendesilva Mar 2, 2023
209aef8
Merge PHPDoc into single sentence
caendesilva Mar 2, 2023
7a4761c
Collapse PHPDoc
caendesilva Mar 2, 2023
f52d507
Remove unnecessary type annotation
caendesilva Mar 2, 2023
9ce0373
Update class documentation
caendesilva Mar 2, 2023
ea80505
Unwrap unnecessary string interpolation
caendesilva Mar 2, 2023
de81274
Unit test the media file helper
caendesilva Mar 2, 2023
dced2b5
Inline unnecessary local test variables
caendesilva Mar 2, 2023
4d74db8
Unwrap unnecessary assertion covered by subsequent one
caendesilva Mar 2, 2023
2fa043e
Inline local variable
caendesilva Mar 2, 2023
91ae41e
Split comma-separated values into multiple lines
caendesilva Mar 2, 2023
32d25f3
Merge concatenated string into helper method as it supports arguments
caendesilva Mar 2, 2023
b811c10
Simplify 'if' with ternary return expression
caendesilva Mar 2, 2023
37122a3
Flip '?:'
caendesilva Mar 2, 2023
8d8dacc
Breaking: Rename `hyde.cache_busting` to `hyde.enable_cache_busting`
caendesilva Mar 2, 2023
95e9469
Document string replacements
caendesilva Mar 2, 2023
93f2c9c
Update code comment
caendesilva Mar 3, 2023
bcaf73e
Merge property annotation into constant annotation
caendesilva Mar 3, 2023
33f1cbc
Breaking: Make public AssetService::$version property protected
caendesilva Mar 3, 2023
3ab44e5
Inline variable
caendesilva Mar 3, 2023
d9f4efd
Rename protected property to cdnUrl to normalize class naming styles
caendesilva Mar 3, 2023
858cd8d
Remove newline between properties
caendesilva Mar 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions config/hyde.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@
|
*/

'cache_busting' => true,
'enable_cache_busting' => true,

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -433,7 +433,7 @@

// Here you can specify HydeFront version and URL for when loading app.css from the CDN.
// Only change these if you know what you're doing as some versions may incompatible with your Hyde version.
// 'hydefront_version' => '',
// 'hydefront_cdn_url' => ''
'hydefront_version' => \Hyde\Framework\Services\AssetService::HYDEFRONT_VERSION,
'hydefront_cdn_url' => \Hyde\Framework\Services\AssetService::HYDEFRONT_CDN_URL,

];
6 changes: 3 additions & 3 deletions packages/framework/config/hyde.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@
|
*/

'cache_busting' => true,
'enable_cache_busting' => true,

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -433,7 +433,7 @@

// Here you can specify HydeFront version and URL for when loading app.css from the CDN.
// Only change these if you know what you're doing as some versions may incompatible with your Hyde version.
// 'hydefront_version' => '',
// 'hydefront_cdn_url' => ''
'hydefront_version' => \Hyde\Framework\Services\AssetService::HYDEFRONT_VERSION,
'hydefront_cdn_url' => \Hyde\Framework\Services\AssetService::HYDEFRONT_CDN_URL,

];
45 changes: 23 additions & 22 deletions packages/framework/src/Framework/Services/AssetService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Hyde\Framework\Services;

use Hyde\Hyde;
use Hyde\Facades\Config;
use Illuminate\Support\Str;
use function str_contains;

Expand All @@ -13,28 +14,26 @@
*
* This class is loaded into the service container, making it easy to access and modify.
*
* The class also provides helper methods for interacting with versioned files,
* as well as the HydeFront CDN service and the media directories.
*
* @see \Hyde\Facades\Asset
*/
class AssetService
{
/**
* The default HydeFront version to load.
*
* @var string HydeFront SemVer Tag
*/
public string $version = 'v2.0';
/** @var string The default HydeFront SemVer tag to load. This constant is set to match the styles used for the installed framework version. */
public final const HYDEFRONT_VERSION = 'v2.0';

/** @var string The default HydeFront CDN path pattern. The Blade-style placeholders are replaced with the proper values. */
public final const HYDEFRONT_CDN_URL = 'https://cdn.jsdelivr.net/npm/hydefront@{{ $version }}/dist/{{ $file }}';

protected ?string $hydefrontUrl = null;
protected string $version = self::HYDEFRONT_VERSION;
protected string $cdnUrl = self::HYDEFRONT_CDN_URL;

public function __construct()
{
if (config('hyde.hydefront_version')) {
$this->version = config('hyde.hydefront_version');
}

if (config('hyde.hydefront_url')) {
$this->hydefrontUrl = config('hyde.hydefront_url');
}
$this->version = Config::getString('hyde.hydefront_version', self::HYDEFRONT_VERSION);
$this->cdnUrl = Config::getString('hyde.hydefront_url', self::HYDEFRONT_CDN_URL);
}

public function version(): string
Expand All @@ -49,18 +48,19 @@ public function cdnLink(string $file): string

public function mediaLink(string $file): string
{
return Hyde::mediaLink("$file").$this->getCacheBustKey($file);
return Hyde::mediaLink($file).$this->getCacheBustKey($file);
}

public function hasMediaFile(string $file): bool
{
return file_exists(Hyde::mediaPath().'/'.$file);
return file_exists(Hyde::mediaPath($file));
}

public function injectTailwindConfig(): string
{
$config = Str::between(file_get_contents(Hyde::path('tailwind.config.js')), '{', '}');

// Remove the plugins array, as it is not used in the frontend.
if (str_contains($config, 'plugins: [')) {
$tokens = explode('plugins: [', $config, 2);
$tokens[1] = Str::after($tokens[1], ']');
Expand All @@ -72,15 +72,16 @@ public function injectTailwindConfig(): string

protected function constructCdnPath(string $file): string
{
return $this->hydefrontUrl ?? 'https://cdn.jsdelivr.net/npm/hydefront@'.$this->version().'/dist/'.$file;
return str_replace(
['{{ $version }}', '{{ $file }}'], [$this->version(), $file],
$this->cdnUrl
);
}

protected function getCacheBustKey(string $file): string
{
if (! config('hyde.cache_busting', true)) {
return '';
}

return '?v='.md5_file(Hyde::mediaPath("$file"));
return Config::getBool('hyde.enable_cache_busting', true)
? '?v='.md5_file(Hyde::mediaPath("$file"))
: '';
}
}
55 changes: 3 additions & 52 deletions packages/framework/tests/Feature/AssetServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,11 @@

/**
* @covers \Hyde\Framework\Services\AssetService
*
* @see \Hyde\Framework\Testing\Unit\AssetServiceUnitTest
*/
class AssetServiceTest extends TestCase
{
public function test_has_version_string()
{
$service = new AssetService();
$this->assertIsString($service->version);
}

public function test_can_change_version()
{
$service = new AssetService();
$service->version = '1.0.0';
$this->assertEquals('1.0.0', $service->version);
}

public function test_version_method_returns_version_property_when_config_override_is_not_set()
{
$service = new AssetService();
$this->assertEquals($service->version, $service->version());
}

public function test_version_can_be_set_in_config()
{
config(['hyde.hydefront_version' => '1.0.0']);
$service = new AssetService();
$this->assertEquals('1.0.0', $service->version());
}

public function test_cdn_path_constructor_returns_cdn_uri()
{
$service = new AssetService();
$this->assertIsString($path = $service->cdnLink('styles.css'));
$this->assertStringContainsString('styles.css', $path);
}

public function test_can_set_custom_cdn_uri_in_config()
{
config(['hyde.hydefront_url' => 'https://example.com']);
$service = new AssetService();
$this->assertSame('https://example.com', $service->cdnLink('styles.css'));
}

public function test_media_link_returns_media_path_with_cache_key()
{
$service = new AssetService();
Expand All @@ -62,7 +24,7 @@ public function test_media_link_returns_media_path_with_cache_key()

public function test_media_link_returns_media_path_without_cache_key_if_cache_busting_is_disabled()
{
config(['hyde.cache_busting' => false]);
config(['hyde.enable_cache_busting' => false]);
$service = new AssetService();
$this->assertIsString($path = $service->mediaLink('app.css'));
$this->assertEquals('media/app.css', $path);
Expand All @@ -78,15 +40,4 @@ public function test_media_link_supports_custom_media_directories()
$this->assertIsString($path = $service->mediaLink('app.css'));
$this->assertEquals('assets/app.css?v='.md5_file(Hyde::path('_assets/app.css')), $path);
}

public function test_inject_tailwind_config_returns_extracted_tailwind_config()
{
$service = new AssetService();
$this->assertIsString($config = $service->injectTailwindConfig());
$this->assertStringContainsString("darkMode: 'class'", $config);
$this->assertStringContainsString('theme: {', $config);
$this->assertStringContainsString('extend: {', $config);
$this->assertStringContainsString('typography: {', $config);
$this->assertStringNotContainsString('plugins', $config);
}
}
2 changes: 1 addition & 1 deletion packages/framework/tests/Feature/MetadataViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected function setUp(): void
parent::setUp();

config(['hyde.url' => 'http://localhost']);
config(['hyde.cache_busting' => false]);
config(['hyde.enable_cache_busting' => false]);
}

protected function build(?string $page = null): void
Expand Down
110 changes: 110 additions & 0 deletions packages/framework/tests/Unit/AssetServiceUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

declare(strict_types=1);

namespace Hyde\Framework\Testing\Unit;

use Hyde\Framework\Services\AssetService;
use Hyde\Testing\UnitTestCase;

/**
* @covers \Hyde\Framework\Services\AssetService
*
* @see \Hyde\Framework\Testing\Feature\AssetServiceTest
*/
class AssetServiceUnitTest extends UnitTestCase
{
protected function setUp(): void
{
self::needsKernel();
self::mockConfig();
}

public function testVersionStringConstant()
{
$this->assertSame('v2.0', AssetService::HYDEFRONT_VERSION);
}

public function testServiceHasVersionString()
{
$this->assertIsString((new AssetService())->version());
}

public function testVersionStringDefaultsToConstant()
{
$this->assertSame(AssetService::HYDEFRONT_VERSION, (new AssetService())->version());
}

public function testVersionCanBeSetInConfig()
{
self::mockConfig(['hyde.hydefront_version' => '1.0.0']);
$this->assertSame('1.0.0', (new AssetService())->version());
}

public function testCdnPatternConstant()
{
$this->assertSame('https://cdn.jsdelivr.net/npm/hydefront@{{ $version }}/dist/{{ $file }}', AssetService::HYDEFRONT_CDN_URL);
}

public function testCanSetCustomCdnUrlInConfig()
{
self::mockConfig(['hyde.hydefront_url' => 'https://example.com']);
$this->assertSame('https://example.com', (new AssetService())->cdnLink(''));
}

public function testCanUseCustomCdnUrlWithVersion()
{
self::mockConfig(['hyde.hydefront_url' => '{{ $version }}']);
$this->assertSame('v2.0', (new AssetService())->cdnLink(''));
}

public function testCanUseCustomCdnUrlWithFile()
{
self::mockConfig(['hyde.hydefront_url' => '{{ $file }}']);
$this->assertSame('styles.css', (new AssetService())->cdnLink('styles.css'));
}

public function testCanUseCustomCdnUrlWithVersionAndFile()
{
self::mockConfig(['hyde.hydefront_url' => '{{ $version }}/{{ $file }}']);
$this->assertSame('v2.0/styles.css', (new AssetService())->cdnLink('styles.css'));
}

public function testCanUseCustomCdnUrlWithCustomVersion()
{
self::mockConfig([
'hyde.hydefront_url' => '{{ $version }}',
'hyde.hydefront_version' => '1.0.0',
]);
$this->assertSame('1.0.0', (new AssetService())->cdnLink(''));
}

public function testCdnLinkHelper()
{
$this->assertSame(
'https://cdn.jsdelivr.net/npm/hydefront@v2.0/dist/styles.css',
(new AssetService())->cdnLink('styles.css')
);
}

public function testHasMediaFileHelper()
{
$this->assertFalse((new AssetService())->hasMediaFile('styles.css'));
}

public function testHasMediaFileHelperReturnsTrueForExistingFile()
{
$this->assertTrue((new AssetService())->hasMediaFile('app.css'));
}

public function testInjectTailwindConfigReturnsExtractedTailwindConfig()
{
$service = new AssetService();
$this->assertIsString($config = $service->injectTailwindConfig());
$this->assertStringContainsString("darkMode: 'class'", $config);
$this->assertStringContainsString('theme: {', $config);
$this->assertStringContainsString('extend: {', $config);
$this->assertStringContainsString('typography: {', $config);
$this->assertStringNotContainsString('plugins', $config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected function setUp(): void
{
parent::setUp();

config(['hyde.cache_busting' => false]);
config(['hyde.enable_cache_busting' => false]);
config(['hyde.navigation.subdirectories' => 'flat']);

$this->needsDirectory('_pages/nested');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ScriptsComponentViewTest extends TestCase

protected function renderTestView(): string
{
config(['hyde.cache_busting' => false]);
config(['hyde.enable_cache_busting' => false]);
$this->mockCurrentPage($this->mockCurrentPage ?? '');

return Blade::render(file_get_contents(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class StylesComponentViewTest extends TestCase

protected function renderTestView(): string
{
config(['hyde.cache_busting' => false]);
config(['hyde.enable_cache_busting' => false]);
$this->mockCurrentPage($this->mockCurrentPage ?? '');

return Blade::render(file_get_contents(
Expand Down