From 7e9bf6d948c0a7687cc81d2d097c6daf25499ea4 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sat, 1 Mar 2008 04:56:11 +0000 Subject: [PATCH] More thorough test_Minify.php Better var/method naming. --- lib/Minify.php | 27 +++++------ lib/Minify/Controller/Base.php | 6 +-- web/test/minify/minified.css | 1 + web/test/minify/minified.js | 12 +++++ web/test/test_Minify.php | 88 ++++++++++++++++++++++++++++++---- 5 files changed, 108 insertions(+), 26 deletions(-) create mode 100644 web/test/minify/minified.css create mode 100644 web/test/minify/minified.js diff --git a/lib/Minify.php b/lib/Minify.php index a8aa859..427e935 100644 --- a/lib/Minify.php +++ b/lib/Minify.php @@ -57,21 +57,21 @@ class Minify { * @param string type This should be the filename of the controller without * extension. e.g. 'Group' * - * @param array $spec options for the controller's constructor + * @param array $ctrlOptions options for the controller's constructor * - * @param array $options options passed on to Minify + * @param array $minOptions options passed on to Minify * * @return mixed false on failure or array of content and headers sent */ - public static function serve($type, $spec = array(), $options = array()) { + public static function serve($type, $ctrlOptions = array(), $minOptions = array()) { $class = 'Minify_Controller_' . $type; if (! class_exists($class, false)) { require_once "Minify/Controller/{$type}.php"; } - $ctrl = new $class($spec, $options); + $ctrl = new $class($ctrlOptions, $minOptions); $ret = self::handleRequest($ctrl); if (false === $ret) { - if (! isset($ctrl->options['quiet']) || ! $ctrl->options['quiet']) { + if (! isset($ctrl->minOptions['quiet']) || ! $ctrl->minOptions['quiet']) { header("HTTP/1.0 400 Bad Request"); exit('400 Bad Request'); } @@ -95,7 +95,7 @@ class Minify { } self::$_controller = $controller; - self::_setOptions(); + self::_resolveOptions($controller->minOptions); $cgOptions = array( 'lastModifiedTime' => self::$_options['lastModifiedTime'] @@ -194,13 +194,12 @@ class Minify { private static $_cache = null; /** - * Set class options based on controller's options and defaults + * Resolve Minify options based on those passed from controller and Minify's defaults * * @return null */ - private static function _setOptions() + private static function _resolveOptions($ctrlOptions) { - $given = self::$_controller->options; self::$_options = array_merge(array( // default options 'isPublic' => true @@ -211,16 +210,16 @@ class Minify { ,'contentTypeCharset' => null // leave out of Content-Type header ,'setExpires' => null // send Expires header ,'quiet' => false - ), $given); + ), $ctrlOptions); $defaultMinifiers = array( 'text/css' => array('Minify_CSS', 'minify') ,'application/x-javascript' => array('Minify_Javascript', 'minify') ,'text/html' => array('Minify_HTML', 'minify') ); - if (! isset($given['minifiers'])) { - $given['minifiers'] = array(); + if (! isset($ctrlOptions['minifiers'])) { + $ctrlOptions['minifiers'] = array(); } - self::$_options['minifiers'] = array_merge($defaultMinifiers, $given['minifiers']); + self::$_options['minifiers'] = array_merge($defaultMinifiers, $ctrlOptions['minifiers']); } /** @@ -238,7 +237,7 @@ class Minify { private static function _fetchContent($encodeMethod) { $cacheId = self::_getCacheId(self::$_controller->sources, self::$_options) - . $encodeMethod; + . $encodeMethod; $content = self::$_cache->get($cacheId, 'Minify'); if (false === $content) { // must generate diff --git a/lib/Minify/Controller/Base.php b/lib/Minify/Controller/Base.php index 67d9b54..304f15c 100644 --- a/lib/Minify/Controller/Base.php +++ b/lib/Minify/Controller/Base.php @@ -18,7 +18,7 @@ class Minify_Controller_Base { public $sources = array(); /** - * @var array options to be read by read by Minify + * @var array options to be read by Minify * * Any unspecified options will use the default values. * @@ -63,7 +63,7 @@ class Minify_Controller_Base { * (bool, default = false) * */ - public $options = array(); + public $minOptions = array(); /** * @var bool was the user request valid @@ -111,7 +111,7 @@ class Minify_Controller_Base { } $options['lastModifiedTime'] = $max; } - $this->options = $options; + $this->minOptions = $options; } /** diff --git a/web/test/minify/minified.css b/web/test/minify/minified.css new file mode 100644 index 0000000..858908b --- /dev/null +++ b/web/test/minify/minified.css @@ -0,0 +1 @@ +@import url(more.css);body,td,th{font-family:Verdana, "Bitstream Vera Sans",sans-serif;font-size:12px}.nav{margin-left:20%}#main-nav{background-color:red;border:1px solid #0f7}div#content h1+p{padding-top:0;margin-top:0}.float-l{float:left}.form-suggest{height:200px;background:#DEE2D0;vertical-align:top}.form-input input{font-size:10px}.hide{display:none}.form-input textarea{font-size:11px;width:350px}.form-label{font-size:10px;font-weight:bold;line-height:25px;padding-right:10px;text-align:right;width:100px;color: #39738F}.font-9{font-size:9px}.form-topic{font-weight:bold}.form-error{color:red}.inline{display:inline}.space-10{clear:both;font-size:10px;height:10px;line-height:10px}.suggest-success{color:green;padding-left:10px;font-size:11px;font-weight:bold}.top{vertical-align:top}table td{padding:3px}a:link,a:active,a:visited,a.postlink{color: #069;text-decoration:none}a:hover{color: #DD6900}a.admin:hover,a.mod:hover{color: #DD6900}a.but,a.but:hover,a.but:visited{color: #000;text-decoration:none}a.topictitle:visited{color: #5493B4}a.topictitle:hover{color: #DD6900}body{color: #000;font:11px Verdana,Arial,Helvetica,sans-serif;margin:0 10px 10px 10px;padding:0;overflow:auto}font,th,td,p{font:12px Verdana,Arial,Helvetica,sans-serif}form{display:inline}hr{border:0px solid #FFF;border-top-width:1px;height:0px}img{border:0 solid}input{font:11px Verdana,Arial,Helvetica,sans-serif}input.button,input.liteoption,.fakebut{background: #FAFAFA;border:1px solid #000;font-size:11px}input.catbutton{background: #FAFAFA;border:1px solid #000;font-size:10px}input.mainoption{background: #FAFAFA;border:1px solid #000;font-size:11px;font-weight:bold}input.post,textarea.post{background: #FFF;border:1px solid #000;font:11px Verdana,Arial,Helvetica,sans-serif;padding-bottom:2px;padding-left:2px}select{background: #FFF;font:11px Verdana,Arial,Helvetica,sans-serif}table{text-align:left}td{vertical-align:middle}td.cat{background-color: #C2C6BA;font-weight:bold;height:20px;letter-spacing:1px;text-indent:4px}td.genmed,.genmed{font-size:11px}td.rowpic{background: #C2C6BA}td.spacerow{background: #E5E6E2}th{background-color: #FADD31;background-image:url(images/cellpic3.gif);background-repeat:repeat-x;color: #68685E;font-size:11px;font-weight:bold;line-height:16px;height:16px;padding-left:8px;padding-right:8px;text-align:center;white-space:nowrap}.admin,.mod{font-size:11px;font-weight:bold}.admin,a.admin,a.admin:visited{color: #FFA34F}.bodyline{background: #FFF;border:1px solid #98AAB1}.center{text-align:center}.code{background: #FAFAFA;border:1px solid #D1D7DC;color: #060;font:12px Courier,"Courier New",sans-serif;padding:5px}.errorline{background: #E5E6E2;border:1px solid #8F8B8B;color:#D92A2A}.explaintitle{color: #5C81B1;font-size:11px;font-weight:bold}.forumline{background: #FFF}.gensmall{font-size:10px}.h1-font{color: #069;display:inline;font:bold 13px Verdana,Arial,Helvetica,sans-serif;margin:0;text-decoration:none}.h2-font{display:inline;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.height1{height:1px}.height22{height:22px}.height25{height:25px}.height28{height:28px}.height30{height:30px}.height40{height:40px}.helpline{border:0 solid;font-size:10px}.imgfolder{margin:1px 4px 1px 4px}.imgspace{margin-left:1px;margin-right:2px}.imgtopic,.imgicon{margin-left:3px}.left{text-align:left}.maintitle,h1,h2{color: #5C81B1;font:bold 20px/120% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;text-decoration:none}.maxwidth{width:100%}.mod,a.mod,a.mod:visited{color: #060}.name{font-size:11px;font-weight:bold}.nav{font-size:11px;font-weight:bold}.nowrap{white-space:nowrap}.postbody{font-size:12px;line-height:125%}.postbody a{text-decoration:underline}.postdetails{color: #00396A;font-size:10px}.quote{background: #F3F3EF;border:1px solid #C2C6BA;color: #069;font-size:11px;line-height:125%}.right{text-align:right}.row1{background: #F0F0EB}.row2,.helpline{background: #E5E6E2}.row3{background: #DBDBD4}.subtitle,h2{font:bold 18px/180% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;text-decoration:none}.topictitle{color: #000;font-size:11px;font-weight:bold}.underline{text-decoration:underline}.top{vertical-align:top}.image-hspace{margin-right:3px}.clear{clear:both} \ No newline at end of file diff --git a/web/test/minify/minified.js b/web/test/minify/minified.js new file mode 100644 index 0000000..5a490ed --- /dev/null +++ b/web/test/minify/minified.js @@ -0,0 +1,12 @@ +(function(){var +reMailto=/^mailto:my_name_is_(\S+)_and_the_domain_is_(\S+)$/,reRemoveTitleIf=/^my name is/,oo=window.onload,fixHrefs=function(){var i=0,l,m;while(l=document.links[i++]){if(m=l.href.match(reMailto)){l.href='mailto:'+m[1]+'@'+m[2];if(reRemoveTitleIf.test(l.title)){l.title='';}}}};window.onload=function(){oo&&oo();fixHrefs();};})();;var MrClay=window.MrClay||{};MrClay.QueryString=function(){var parse=function(str){var assignments=str.split('&'),obj={},propValue;for(var i=0,l=assignments.length;i2||-1!=propValue[0].indexOf('+')||propValue[0]==''){continue;} +if(propValue.length==1){propValue[1]=propValue[0];} +obj[unescape(propValue[0])]=unescape(propValue[1].replace(/\+/g,' '));} +return obj;};function construct_(spec){spec=spec||window;if(typeof spec=='object'){this.window=spec;spec=spec.location.search.substr(1);}else{this.window=window;} +this.vars=parse(spec);} +construct_.reload=function(vars,window_){window_=window_||window;vars=vars||(new MrClay.QueryString(window_)).vars;var l=window_.location,currUrl=l.href,s=MrClay.QueryString.toString(vars),newUrl=l.protocol+'//'+l.hostname+l.pathname ++(s?'?'+s:'')+l.hash;if(currUrl==newUrl){l.reload();}else{l.assign(newUrl);}};construct_.get=function(key,default_,window_){window_=window_||window;return(new MrClay.QueryString(window_)).get(key,default_);};construct_.set=function(key,value,window_){window_=window_||window;(new MrClay.QueryString(window_)).set(key,value).reload();};construct_.toString=function(vars){var pieces=[];for(var prop in vars){pieces.push(escape(prop)+'='+escape(vars[prop]));} +return pieces.join('&');};construct_.prototype.reload=function(){MrClay.QueryString.reload(this.vars,this.window);return this;};construct_.prototype.get=function(key,default_){if(typeof default_=='undefined'){default_=null;} +return(this.vars[key]==null)?default_:this.vars[key];};construct_.prototype.set=function(key,value){var obj={};if(typeof key=='string'){obj[key]=value;}else{obj=key;} +for(var prop in obj){if(obj[prop]==null){delete this.vars[prop];}else{this.vars[prop]=obj[prop];}} +return this;};construct_.prototype.toString=function(){return QueryString.toString(this.vars);};return construct_;}(); \ No newline at end of file diff --git a/web/test/test_Minify.php b/web/test/test_Minify.php index db755fc..1489bbe 100644 --- a/web/test/test_Minify.php +++ b/web/test/test_Minify.php @@ -1,23 +1,93 @@ preg_replace('/\\r\\n?/', "\n", file_get_contents($thisDir . '/minify/minified.js')) + ,'headers' => array ( + 'Cache-Control' => 'public', + 'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $tomorrow), + 'Content-Type' => 'application/x-javascript', + ) +); +$output = Minify::serve('Files', array( $thisDir . '/minify/email.js' ,$thisDir . '/minify/QueryString.js' +), array( + 'quiet' => true + ,'setExpires' => $tomorrow + ,'encodeOutput' => false )); +$passed = assertTrue($expected === $output, 'Minify - JS and Expires'); +echo "\nOutput: " .var_export($output, 1). "\n\n"; +if (! $passed) { + echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; +} + + + +// Test minifying CSS and responding with Etag/Last-Modified + +// don't allow conditional headers +unset($_SERVER['HTTP_IF_NONE_MATCH'], $_SERVER['HTTP_IF_MODIFIED_SINCE']); + +$expected = array( + 'content' => file_get_contents($thisDir . '/minify/minified.css') + ,'headers' => array ( + 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), + 'ETag' => "\"{$lastModified}pub\"", + 'Cache-Control' => 'max-age=0, public, must-revalidate', + 'Content-Type' => 'text/css', + ) +); +$output = Minify::serve('Files', array( + $thisDir . '/css/styles.css' + ,$thisDir . '/css/subsilver.css' +), array( + 'quiet' => true + ,'lastModifiedTime' => $lastModified + ,'encodeOutput' => false +)); +$passed = assertTrue($expected === $output, 'Minify - CSS and Etag/Last-Modified'); +echo "\nOutput: " .var_export($output, 1). "\n\n"; +if (! $passed) { + echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; +} + + +// Test 304 response + +// simulate conditional headers +$_SERVER['HTTP_IF_NONE_MATCH'] = "\"{$lastModified}pub\""; +$_SERVER['HTTP_IF_MODIFIED_SINCE'] = gmdate('D, d M Y H:i:s \G\M\T', $lastModified); + +$expected = array ( + 'content' => '', + 'headers' => array ( + '_responseCode' => 'HTTP/1.0 304 Not Modified', + ), +); +$output = Minify::serve('Files', array( + $thisDir . '/css/styles.css' +), array( + 'quiet' => true + ,'lastModifiedTime' => $lastModified + ,'encodeOutput' => false +)); +$passed = assertTrue($expected === $output, 'Minify - 304 response'); +echo "\nOutput: " .var_export($output, 1). "\n\n"; +if (! $passed) { + echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; +}