WIP: VERSION: 03.07.00 > Link asset minification to Joomla cache system #62
1
src/media/css/colors/dark/colors_alternative.min.css
vendored
Normal file
1
src/media/css/colors/dark/colors_alternative.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/media/css/colors/dark/colors_standard.min.css
vendored
Normal file
1
src/media/css/colors/dark/colors_standard.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/media/css/colors/light/colors_alternative.min.css
vendored
Normal file
1
src/media/css/colors/light/colors_alternative.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/media/css/colors/light/colors_standard.min.css
vendored
Normal file
1
src/media/css/colors/light/colors_standard.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/media/css/editor.min.css
vendored
Normal file
1
src/media/css/editor.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
@charset "UTF-8";body{font-size:1rem;font-weight:400;line-height:1.5;color:#22262a;background-color:#fff}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0.5rem;font-weight:700;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}h2{font-size:calc(1.325rem + 0.9vw)}h3{font-size:calc(1.3rem + 0.6vw)}h4{font-size:calc(1.275rem + 0.3vw)}h5{font-size:1.25rem}h6{font-size:1rem}a{text-decoration:none}a:link{color:#224faa}a:hover{color:#424077}p{margin-top:0;margin-bottom:1rem}hr#system-readmore{color:#f00;border:#f00 dashed 1px}span[lang]{padding:2px;border:1px dashed #bbb}span[lang]:after{font-size:smaller;color:#f00;vertical-align:super;content:attr(lang)}
|
||||
1
src/media/css/template.min.css
vendored
Normal file
1
src/media/css/template.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
19
src/media/css/user.css
Normal file
19
src/media/css/user.css
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: Moko-Cassiopeia
|
||||
REPO: https://github.com/mokoconsulting-tech/moko-cassiopeia
|
||||
PATH: ./media/css/user.css
|
||||
VERSION: 03.05.00
|
||||
BRIEF: User custom styles - add your custom CSS here
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is intentionally empty and available for user customizations.
|
||||
* Add your custom CSS rules here to override template styles.
|
||||
*/
|
||||
0
src/media/css/user.min.css
vendored
Normal file
0
src/media/css/user.min.css
vendored
Normal file
1
src/media/js/darkmode-toggle.min.js
vendored
Normal file
1
src/media/js/darkmode-toggle.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(){'use strict';var STORAGE_KEY='theme';var docEl=document.documentElement;var mql=window.matchMedia('(prefers-color-scheme: dark)');function getStored(){try{return localStorage.getItem(STORAGE_KEY);}catch(e){return null;}}function setStored(v){try{localStorage.setItem(STORAGE_KEY,v);}catch(e){}}function clearStored(){try{localStorage.removeItem(STORAGE_KEY);}catch(e){}}function systemTheme(){return mql.matches ? 'dark' : 'light';}function applyTheme(theme){docEl.setAttribute('data-bs-theme',theme);docEl.setAttribute('data-aria-theme',theme);var meta=document.querySelector('meta[name="theme-color"]');if(meta){meta.setAttribute('content',theme==='dark' ? '#0f1115' : '#ffffff');}var sw=document.getElementById('mokoThemeSwitch');if(sw){sw.setAttribute('aria-checked',theme==='dark' ? 'true' : 'false');}}function initTheme(){var stored=getStored();applyTheme(stored ? stored : systemTheme());}function posClassFromBody(){var pos=(document.body.getAttribute('data-theme-fab-pos')||'br').toLowerCase();if(!/^(br|bl|tr|tl)$/.test(pos))pos='br';return 'pos-'+pos;}function buildToggle(){if(document.getElementById('mokoThemeFab'))return;var wrap=document.createElement('div');wrap.id='mokoThemeFab';wrap.className=posClassFromBody();var lblL=document.createElement('span');lblL.className='label';lblL.textContent='Light';var switchWrap=document.createElement('button');switchWrap.id='mokoThemeSwitch';switchWrap.type='button';switchWrap.setAttribute('role','switch');switchWrap.setAttribute('aria-label','Toggle dark mode');switchWrap.setAttribute('aria-checked','false');var track=document.createElement('span');track.className='switch';var knob=document.createElement('span');knob.className='knob';track.appendChild(knob);switchWrap.appendChild(track);var lblD=document.createElement('span');lblD.className='label';lblD.textContent='Dark';var auto=document.createElement('button');auto.id='mokoThemeAuto';auto.type='button';auto.className='btn btn-sm btn-link text-decoration-none px-2';auto.setAttribute('aria-label','Follow system theme');auto.textContent='Auto';switchWrap.addEventListener('click',function(){var current=(docEl.getAttribute('data-bs-theme')||'light').toLowerCase();var next=current==='dark' ? 'light' : 'dark';applyTheme(next);setStored(next);});auto.addEventListener('click',function(){clearStored();applyTheme(systemTheme());});var onMql=function(){if(!getStored())applyTheme(systemTheme());};if(typeof mql.addEventListener==='function')mql.addEventListener('change',onMql);else if(typeof mql.addListener==='function')mql.addListener(onMql);var initial=getStored()||systemTheme();switchWrap.setAttribute('aria-checked',initial==='dark' ? 'true' : 'false');wrap.appendChild(lblL);wrap.appendChild(switchWrap);wrap.appendChild(lblD);wrap.appendChild(auto);document.body.appendChild(wrap);window.mokoThemeFabStatus=function(){var el=document.getElementById('mokoThemeFab');if(!el)return{mounted: false};var r=el.getBoundingClientRect();return{mounted: true,rect:{top: r.top,left: r.left,width: r.width,height: r.height},zIndex: window.getComputedStyle(el).zIndex,posClass: el.className};};setTimeout(function(){var r=wrap.getBoundingClientRect();if(r.width<10||r.height<10){wrap.classList.add('debug-outline');console.warn('[moko]Theme FAB mounted but appears too small — check CSS collisions.');}},50);}function init(){initTheme();buildToggle();}if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',init);}else{init();}})();
|
||||
1
src/media/js/gtm.min.js
vendored
Normal file
1
src/media/js/gtm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/media/js/template.min.js
vendored
Normal file
1
src/media/js/template.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(win,doc){"use strict";function backToTop(){win.scrollTo({top: 0,behavior: "smooth"});}function handleScroll(){if(win.scrollY>50){doc.body.classList.add("scrolled");}else{doc.body.classList.remove("scrolled");}}function initTOC(){if(typeof win.Toc==="function"&&doc.querySelector("#toc")){win.Toc.init({$nav: $("#toc"),$scope: $("main")});}}function initDrawers(){var leftBtn=doc.querySelector(".drawer-toggle-left");var rightBtn=doc.querySelector(".drawer-toggle-right");if(leftBtn){leftBtn.addEventListener("click",function(){var target=doc.querySelector(leftBtn.getAttribute("data-bs-target"));if(target)new bootstrap.Offcanvas(target).show();});}if(rightBtn){rightBtn.addEventListener("click",function(){var target=doc.querySelector(rightBtn.getAttribute("data-bs-target"));if(target)new bootstrap.Offcanvas(target).show();});}}function initBackTop(){var backTop=doc.getElementById("back-top");if(backTop){backTop.addEventListener("click",function(e){e.preventDefault();backToTop();});}}function init(){handleScroll();win.addEventListener("scroll",handleScroll);initTOC();initDrawers();initBackTop();}if(doc.readyState==="loading"){doc.addEventListener("DOMContentLoaded",init);}else{init();}})(window,document);
|
||||
1
src/media/js/theme-init.min.js
vendored
Normal file
1
src/media/js/theme-init.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(function(win,doc){"use strict";var storageKey="theme";var mql=win.matchMedia("(prefers-color-scheme: dark)");var root=doc.documentElement;function applyTheme(theme){root.setAttribute("data-bs-theme",theme);root.setAttribute("data-aria-theme",theme);try{localStorage.setItem(storageKey,theme);}catch(e){}}function clearStored(){try{localStorage.removeItem(storageKey);}catch(e){}}function systemTheme(){return mql.matches ? "dark" : "light";}function init(){var stored=null;try{stored=localStorage.getItem(storageKey);}catch(e){}var theme=stored ? stored : systemTheme();applyTheme(theme);var onChange=function(){if(!localStorage.getItem(storageKey)){applyTheme(systemTheme());}};if(typeof mql.addEventListener==="function"){mql.addEventListener("change",onChange);}else if(typeof mql.addListener==="function"){mql.addListener(onChange);}var switchEl=doc.getElementById("themeSwitch");var autoBtn=doc.getElementById("themeAuto");if(switchEl){switchEl.checked=(theme==="dark");switchEl.addEventListener("change",function(){var choice=switchEl.checked ? "dark" : "light";applyTheme(choice);});}if(autoBtn){autoBtn.addEventListener("click",function(){clearStored();applyTheme(systemTheme());});}}if(doc.readyState==="loading"){doc.addEventListener("DOMContentLoaded",init);}else{init();}})(window,document);
|
||||
4
src/media/vendor/afeld/bootstrap-toc.min.css
vendored
4
src/media/vendor/afeld/bootstrap-toc.min.css
vendored
@@ -1,4 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/)
|
||||
* Copyright 2015 Aidan Feldman
|
||||
* Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */nav[data-toggle=toc] .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}nav[data-toggle=toc] .nav>li>a:focus,nav[data-toggle=toc] .nav>li>a:hover{padding-left:19px;color:#563d7c;text-decoration:none;background-color:transparent;border-left:1px solid #563d7c}nav[data-toggle=toc] .nav-link.active,nav[data-toggle=toc] .nav-link.active:focus,nav[data-toggle=toc] .nav-link.active:hover{padding-left:18px;font-weight:700;color:#563d7c;background-color:transparent;border-left:2px solid #563d7c}nav[data-toggle=toc] .nav-link+ul{display:none;padding-bottom:10px}nav[data-toggle=toc] .nav .nav>li>a{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}nav[data-toggle=toc] .nav .nav>li>a:focus,nav[data-toggle=toc] .nav .nav>li>a:hover{padding-left:29px}nav[data-toggle=toc] .nav .nav>li>.active,nav[data-toggle=toc] .nav .nav>li>.active:focus,nav[data-toggle=toc] .nav .nav>li>.active:hover{padding-left:28px;font-weight:500}nav[data-toggle=toc] .nav-link.active+ul{display:block}
|
||||
5
src/media/vendor/afeld/bootstrap-toc.min.js
vendored
5
src/media/vendor/afeld/bootstrap-toc.min.js
vendored
@@ -1,5 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/)
|
||||
* Copyright 2015 Aidan Feldman
|
||||
* Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
|
||||
!function(a){"use strict";window.Toc={helpers:{findOrFilter:function(e,t){var n=e.find(t);return e.filter(t).add(n).filter(":not([data-toc-skip])")},generateUniqueIdBase:function(e){return a(e).text().trim().replace(/\'/gi,"").replace(/[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,64).replace(/^-+|-+$/gm,"").toLowerCase()||e.tagName.toLowerCase()},generateUniqueId:function(e){for(var t=this.generateUniqueIdBase(e),n=0;;n++){var r=t;if(0<n&&(r+="-"+n),!document.getElementById(r))return r}},generateAnchor:function(e){if(e.id)return e.id;var t=this.generateUniqueId(e);return e.id=t},createNavList:function(){return a('<ul class="nav navbar-nav"></ul>')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a('<a class="nav-link"></a>');n.attr("href","#"+e),n.text(t);var r=a("<li></li>");return r.append(n),r},generateNavItem:function(e){var t=this.generateAnchor(e),n=a(e),r=n.data("toc-text")||n.text();return this.generateNavEl(t,r)},getTopLevel:function(e){for(var t=1;t<=6;t++){if(1<this.findOrFilter(e,"h"+t).length)return t}return 1},getHeadings:function(e,t){var n="h"+t,r="h"+(t+1);return this.findOrFilter(e,n+","+r)},getNavLevel:function(e){return parseInt(e.tagName.charAt(1),10)},populateNav:function(r,a,e){var i,s=r,c=this;e.each(function(e,t){var n=c.generateNavItem(t);c.getNavLevel(t)===a?s=r:i&&s===r&&(s=c.createChildNavList(i)),s.append(n),i=n})},parseOps:function(e){var t;return(t=e.jquery?{$nav:e}:e).$scope=t.$scope||a(document.body),t}},init:function(e){(e=this.helpers.parseOps(e)).$nav.attr("data-toggle","toc");var t=this.helpers.createChildNavList(e.$nav),n=this.helpers.getTopLevel(e.$scope),r=this.helpers.getHeadings(e.$scope,n);this.helpers.populateNav(t,n,r)}},a(function(){a('nav[data-toggle="toc"]').each(function(e,t){var n=a(t);Toc.init(n)})})}(jQuery);
|
||||
9
src/media/vendor/fa7free/css/all.min.css
vendored
9
src/media/vendor/fa7free/css/all.min.css
vendored
File diff suppressed because one or more lines are too long
6
src/media/vendor/fa7free/css/brands.min.css
vendored
6
src/media/vendor/fa7free/css/brands.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
src/media/vendor/fa7free/css/regular.min.css
vendored
6
src/media/vendor/fa7free/css/regular.min.css
vendored
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2025 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-family-classic:"Font Awesome 7 Free";--fa-font-regular:normal 400 1em/1 var(--fa-family-classic);--fa-style-family-classic:var(--fa-family-classic)}@font-face{font-family:"Font Awesome 7 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2)}.far{--fa-style:400}.fa-classic,.far{--fa-family:var(--fa-family-classic)}.fa-regular{--fa-style:400}
|
||||
6
src/media/vendor/fa7free/css/solid.min.css
vendored
6
src/media/vendor/fa7free/css/solid.min.css
vendored
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2025 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-family-classic:"Font Awesome 7 Free";--fa-font-solid:normal 900 1em/1 var(--fa-family-classic);--fa-style-family-classic:var(--fa-family-classic)}@font-face{font-family:"Font Awesome 7 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2)}.fas{--fa-style:900}.fa-classic,.fas{--fa-family:var(--fa-family-classic)}.fa-solid{--fa-style:900}
|
||||
221
tests/unit/AssetMinifierTest.php
Normal file
221
tests/unit/AssetMinifierTest.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Codeception\Test\Unit;
|
||||
use Tests\Support\UnitTester;
|
||||
|
||||
/**
|
||||
* Unit tests for AssetMinifier class
|
||||
*/
|
||||
class AssetMinifierTest extends Unit
|
||||
{
|
||||
protected UnitTester $tester;
|
||||
|
||||
private string $testDir;
|
||||
private string $testCssFile;
|
||||
private string $testJsFile;
|
||||
|
||||
protected function _before()
|
||||
{
|
||||
// Create temporary test directory
|
||||
$this->testDir = sys_get_temp_dir() . '/moko-cassiopeia-test-' . uniqid();
|
||||
mkdir($this->testDir, 0777, true);
|
||||
|
||||
$this->testCssFile = $this->testDir . '/test.css';
|
||||
$this->testJsFile = $this->testDir . '/test.js';
|
||||
|
||||
// Load the AssetMinifier class
|
||||
require_once __DIR__ . '/../../src/templates/AssetMinifier.php';
|
||||
}
|
||||
|
||||
protected function _after()
|
||||
{
|
||||
// Clean up test directory
|
||||
if (is_dir($this->testDir)) {
|
||||
$this->deleteDirectory($this->testDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to recursively delete a directory
|
||||
*/
|
||||
private function deleteDirectory(string $dir): void
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($files as $file) {
|
||||
$path = $dir . '/' . $file;
|
||||
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
|
||||
}
|
||||
rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CSS minification
|
||||
*/
|
||||
public function testMinifyCSS()
|
||||
{
|
||||
$css = "
|
||||
/* This is a comment */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
";
|
||||
|
||||
$minified = \AssetMinifier::minifyCSS($css);
|
||||
|
||||
// Should remove comments
|
||||
$this->assertStringNotContainsString('/* This is a comment */', $minified);
|
||||
|
||||
// Should remove whitespace
|
||||
$this->assertStringNotContainsString("\n", $minified);
|
||||
$this->assertStringNotContainsString(" ", $minified);
|
||||
|
||||
// Should still contain the actual CSS
|
||||
$this->assertStringContainsString('body{', $minified);
|
||||
$this->assertStringContainsString('margin:0', $minified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test JavaScript minification
|
||||
*/
|
||||
public function testMinifyJS()
|
||||
{
|
||||
$js = "
|
||||
// This is a single-line comment
|
||||
function hello() {
|
||||
/* Multi-line
|
||||
comment */
|
||||
console.log('Hello World');
|
||||
return true;
|
||||
}
|
||||
";
|
||||
|
||||
$minified = \AssetMinifier::minifyJS($js);
|
||||
|
||||
// Should remove comments
|
||||
$this->assertStringNotContainsString('// This is a single-line comment', $minified);
|
||||
$this->assertStringNotContainsString('/* Multi-line', $minified);
|
||||
|
||||
// Should still contain the function
|
||||
$this->assertStringContainsString('function hello()', $minified);
|
||||
$this->assertStringContainsString("console.log('Hello World')", $minified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test minifying CSS file
|
||||
*/
|
||||
public function testMinifyCSSFile()
|
||||
{
|
||||
$css = "body { margin: 0; padding: 0; }";
|
||||
file_put_contents($this->testCssFile, $css);
|
||||
|
||||
$minFile = $this->testDir . '/test.min.css';
|
||||
$result = \AssetMinifier::minifyFile($this->testCssFile, $minFile);
|
||||
|
||||
$this->assertTrue($result, 'Minification should succeed');
|
||||
$this->assertFileExists($minFile, 'Minified file should exist');
|
||||
|
||||
$content = file_get_contents($minFile);
|
||||
$this->assertNotEmpty($content, 'Minified file should not be empty');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test minifying JavaScript file
|
||||
*/
|
||||
public function testMinifyJSFile()
|
||||
{
|
||||
$js = "function test() { return true; }";
|
||||
file_put_contents($this->testJsFile, $js);
|
||||
|
||||
$minFile = $this->testDir . '/test.min.js';
|
||||
$result = \AssetMinifier::minifyFile($this->testJsFile, $minFile);
|
||||
|
||||
$this->assertTrue($result, 'Minification should succeed');
|
||||
$this->assertFileExists($minFile, 'Minified file should exist');
|
||||
|
||||
$content = file_get_contents($minFile);
|
||||
$this->assertNotEmpty($content, 'Minified file should not be empty');
|
||||
$this->assertStringContainsString('function test()', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test minifying non-existent file
|
||||
*/
|
||||
public function testMinifyNonExistentFile()
|
||||
{
|
||||
$result = \AssetMinifier::minifyFile(
|
||||
$this->testDir . '/nonexistent.css',
|
||||
$this->testDir . '/output.min.css'
|
||||
);
|
||||
|
||||
$this->assertFalse($result, 'Should return false for non-existent file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deleting minified files
|
||||
*/
|
||||
public function testDeleteMinifiedFiles()
|
||||
{
|
||||
// Create some test files
|
||||
file_put_contents($this->testDir . '/file1.css', 'body{}');
|
||||
file_put_contents($this->testDir . '/file1.min.css', 'body{}');
|
||||
file_put_contents($this->testDir . '/file2.js', 'var x=1;');
|
||||
file_put_contents($this->testDir . '/file2.min.js', 'var x=1;');
|
||||
|
||||
// Create subdirectory with minified files
|
||||
$subDir = $this->testDir . '/sub';
|
||||
mkdir($subDir);
|
||||
file_put_contents($subDir . '/sub.min.css', 'div{}');
|
||||
|
||||
$deleted = \AssetMinifier::deleteMinifiedFiles($this->testDir);
|
||||
|
||||
$this->assertGreaterThanOrEqual(3, $deleted, 'Should delete at least 3 minified files');
|
||||
$this->assertFileDoesNotExist($this->testDir . '/file1.min.css');
|
||||
$this->assertFileDoesNotExist($this->testDir . '/file2.min.js');
|
||||
$this->assertFileDoesNotExist($subDir . '/sub.min.css');
|
||||
|
||||
// Non-minified files should still exist
|
||||
$this->assertFileExists($this->testDir . '/file1.css');
|
||||
$this->assertFileExists($this->testDir . '/file2.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test process assets in development mode
|
||||
*/
|
||||
public function testProcessAssetsDevelopmentMode()
|
||||
{
|
||||
// Create some minified files
|
||||
file_put_contents($this->testDir . '/test.min.css', 'body{}');
|
||||
file_put_contents($this->testDir . '/test.min.js', 'var x=1;');
|
||||
|
||||
$result = \AssetMinifier::processAssets($this->testDir, true);
|
||||
|
||||
$this->assertEquals('development', $result['mode']);
|
||||
$this->assertGreaterThanOrEqual(2, $result['deleted'], 'Should delete minified files');
|
||||
$this->assertFileDoesNotExist($this->testDir . '/test.min.css');
|
||||
$this->assertFileDoesNotExist($this->testDir . '/test.min.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test process assets returns error for non-existent directory
|
||||
*/
|
||||
public function testProcessAssetsNonExistentDirectory()
|
||||
{
|
||||
$result = \AssetMinifier::processAssets('/nonexistent/path', false);
|
||||
|
||||
$this->assertNotEmpty($result['errors']);
|
||||
$this->assertStringContainsString('does not exist', $result['errors'][0]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user