Completed
Push — master ( ab0c5b...215915 )
by frank
01:41
created

AOTest::test_network_per_site_settings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 15
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
class AOTest extends WP_UnitTestcase
4
{
5
    /**
6
     * Plugin instance/fixture used in some tests.
7
     *
8
     * @var autoptimizeMain
9
     */
10
    protected $ao;
11
12
    protected static $flexible_url_parts_js = [
13
        'default'          => 'wp-content/cache/autoptimize/js/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
14
        'custom'           => 'wp-content/c/ao/js/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
15
        'multisite'        => 'wp-content/cache/autoptimize/1/js/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
16
        'multisite_custom' => 'wp-content/c/ao/1/js/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
17
    ];
18
19
    protected static $flexible_url_parts_css = [
20
        'default'          => 'wp-content/cache/autoptimize/css/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
21
        'custom'           => 'wp-content/c/ao/css/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
22
        'multisite'        => 'wp-content/cache/autoptimize/1/css/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
23
        'multisite_custom' => 'wp-content/c/ao/1/css/' . AUTOPTIMIZE_CACHEFILE_PREFIX,
24
    ];
25
26
    protected function getAoStylesDefaultOptions()
27
    {
28
        $conf = autoptimizeConfig::instance();
29
30
        return [
31
            'aggregate'       => $conf->get( 'autoptimize_css_aggregate' ),
32
            'justhead'        => $conf->get( 'autoptimize_css_justhead' ),
33
            'datauris'        => $conf->get( 'autoptimize_css_datauris' ),
34
            'defer'           => $conf->get( 'autoptimize_css_defer' ),
35
            'defer_inline'    => $conf->get( 'autoptimize_css_defer_inline' ),
36
            'inline'          => $conf->get( 'autoptimize_css_inline' ),
37
            'css_exclude'     => $conf->get( 'autoptimize_css_exclude' ),
38
            'cdn_url'         => $conf->get( 'autoptimize_cdn_url' ),
39
            'include_inline'  => $conf->get( 'autoptimize_css_include_inline' ),
40
            'nogooglefont'    => $conf->get( 'autoptimize_css_nogooglefont' ),
41
            'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
42
        ];
43
    }
44
45
    protected function getAoScriptsDefaultOptions()
46
    {
47
        $conf = autoptimizeConfig::instance();
48
49
        return [
50
            'aggregate'       => $conf->get( 'autoptimize_js_aggregate' ),
51
            'justhead'        => $conf->get( 'autoptimize_js_justhead' ),
52
            'forcehead'       => $conf->get( 'autoptimize_js_forcehead' ),
53
            'trycatch'        => $conf->get( 'autoptimize_js_trycatch' ),
54
            'js_exclude'      => $conf->get( 'autoptimize_js_exclude' ),
55
            'cdn_url'         => $conf->get( 'autoptimize_cdn_url' ),
56
            'include_inline'  => $conf->get( 'autoptimize_js_include_inline' ),
57
            'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
58
        ];
59
    }
60
61
    /**
62
     * @return array
63
     */
64
    protected function get_urls()
65
    {
66
        static $site_url = null;
67
        if ( null === $site_url ) {
68
            $site_url = site_url();
69
        }
70
71
        static $cdn_url = null;
72
        if ( null === $cdn_url ) {
73
            $cdn_url = autoptimizeOptionWrapper::get_option( 'autoptimize_cdn_url' );
74
        }
75
76
        static $imgopt_host = null;
77
        if ( null === $imgopt_host ) {
78
            $optimizer   = new autoptimizeImages();
79
            $imgopt_host = rtrim( $optimizer->get_imgopt_host(), '/' );
80
        }
81
82
        static $urls = [];
83
84
        if ( empty( $urls ) ) {
85
            $parts = autoptimizeUtils::get_ao_wp_site_url_parts();
86
            $urls  = [
87
                'siteurl'    => $site_url,
88
                'prsiteurl'  => '//' . str_replace( array( 'http://', 'https://' ), '', $site_url ),
89
                'wwwsiteurl' => $parts['scheme'] . '://www.' . str_replace( 'www.', '', $parts['host'] ),
90
                'cdnurl'     => $cdn_url,
91
                'imgopthost' => $imgopt_host,
92
                'subfolder'  => '',
93
            ];
94
95
            if ( AO_TEST_SUBFOLDER_INSTALL ) {
96
                $urls['subfolder'] = 'wordpress/';
97
            }
98
        }
99
100
        return $urls;
101
    }
102
103
    /**
104
     * Runs before each test method.
105
     */
106
    public function setUp()
107
    {
108
        $this->ao = new autoptimizeMain( AUTOPTIMIZE_PLUGIN_VERSION, AUTOPTIMIZE_PLUGIN_FILE );
109
110
        parent::setUp();
111
    }
112
113
    /**
114
     * Runs after each test method.
115
     */
116
    public function tearDown()
117
    {
118
        // Making sure certain filters are removed after each test to ensure isolation.
119
        $filter_tags = array(
120
            'autoptimize_filter_noptimize',
121
            'autoptimize_filter_base_cdnurl',
122
            'autoptimize_filter_css_is_datauri_candidate',
123
            'autoptimize_filter_css_datauri_image',
124
            'autoptimize_filter_css_inlinesize',
125
            'autoptimize_filter_css_fonts_cdn',
126
        );
127
        foreach ( $filter_tags as $filter_tag ) {
128
            remove_all_filters( $filter_tag );
129
        }
130
131
        parent::tearDown();
132
    }
133
134
    protected function get_test_markup()
135
    {
136
        $siteurl = $this->get_urls()['siteurl'];
137
138
        $markup = <<<MARKUP
139
<!DOCTYPE html>
140
<!--[if lt IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8 lt-ie7"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
141
<!--[if IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
142
<!--[if IE 8]> <html class="no-svg no-js lt-ie9"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
143
<!--[if gt IE 8]><!--> <html class="no-svg no-js"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <!--<![endif]-->
144
<head>
145
<meta charset="utf-8">
146
<title>Mliječna juha od brokule &#9832; Kuhaj.hr</title>
147
<meta name="viewport" content="width=device-width,initial-scale=1">
148
<style type="text/css">
149
/* cdn rewrite tests */
150
151
.bg { background:url('img/something.svg'); }
152
.bg-no-quote { background: url(img/something.svg); }
153
.bg-double-quotes { background: url("img/something.svg"); }
154
155
.whitespaces { background : url   (  "../../somewhere-else/svg.svg" ) ; }
156
157
.host-relative { background: url("/img/something.svg"); }
158
.protocol-relative { background: url("//something/somewhere/example.png"); }
159
160
/* roboto-100 - latin-ext_latin */
161
@font-face {
162
    font-family: 'Roboto';
163
    font-style: normal;
164
    font-weight: 100;
165
    src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
166
    src: local('Roboto Thin'), local('Roboto-Thin'),
167
        url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
168
        url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
169
        url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
170
        url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
171
        url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
172
}
173
/* roboto-300 - latin-ext_latin */
174
@font-face {
175
    font-family: 'Roboto';
176
    font-style: normal;
177
    font-weight: 300;
178
    src: url('../fonts/roboto-v15-latin-ext_latin-300.eot'); /* IE9 Compat Modes */
179
    src: local('Roboto Light'), local('Roboto-Light'),
180
        url('../fonts/roboto-v15-latin-ext_latin-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
181
        url('../fonts/roboto-v15-latin-ext_latin-300.woff2') format('woff2'), /* Super Modern Browsers */
182
        url('../fonts/roboto-v15-latin-ext_latin-300.woff') format('woff'), /* Modern Browsers */
183
        url('../fonts/roboto-v15-latin-ext_latin-300.ttf') format('truetype'), /* Safari, Android, iOS */
184
        url('../fonts/roboto-v15-latin-ext_latin-300.svg#Roboto') format('svg'); /* Legacy iOS */
185
}
186
/* roboto-regular - latin-ext_latin */
187
@font-face {
188
    font-family: 'Roboto';
189
    font-style: normal;
190
    font-weight: 400;
191
    src: url('../fonts/roboto-v15-latin-ext_latin-regular.eot'); /* IE9 Compat Modes */
192
    src: local('Roboto'), local('Roboto-Regular'),
193
        url('../fonts/roboto-v15-latin-ext_latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
194
        url('../fonts/roboto-v15-latin-ext_latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
195
        url('../fonts/roboto-v15-latin-ext_latin-regular.woff') format('woff'), /* Modern Browsers */
196
        url('../fonts/roboto-v15-latin-ext_latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
197
        url('../fonts/roboto-v15-latin-ext_latin-regular.svg#Roboto') format('svg'); /* Legacy iOS */
198
}
199
/* roboto-500 - latin-ext_latin */
200
@font-face {
201
    font-family: 'Roboto';
202
    font-style: normal;
203
    font-weight: 500;
204
    src: url('../fonts/roboto-v15-latin-ext_latin-500.eot'); /* IE9 Compat Modes */
205
    src: local('Roboto Medium'), local('Roboto-Medium'),
206
        url('../fonts/roboto-v15-latin-ext_latin-500.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
207
        url('../fonts/roboto-v15-latin-ext_latin-500.woff2') format('woff2'), /* Super Modern Browsers */
208
        url('../fonts/roboto-v15-latin-ext_latin-500.woff') format('woff'), /* Modern Browsers */
209
        url('../fonts/roboto-v15-latin-ext_latin-500.ttf') format('truetype'), /* Safari, Android, iOS */
210
        url('../fonts/roboto-v15-latin-ext_latin-500.svg#Roboto') format('svg'); /* Legacy iOS */
211
}
212
</style>
213
    <!--[if lt IE 9]>
214
    <script src="$siteurl/wp-content/themes/my-theme/js/vendor/html5shiv-printshiv.min.js" type="text/javascript"></script>
215
    <![endif]-->
216
    <!--[if (gte IE 6)&(lte IE 8)]>
217
        <script type="text/javascript" src="$siteurl/wp-content/themes/my-theme/js/vendor/respond.min.js"></script>
218
    <![endif]-->
219
</head>
220
221
<body class="single single-post">
222
223
    <div id="fb-root"></div>
224
    <script>(function(d, s, id) {
225
        var js, fjs = d.getElementsByTagName(s)[0];
226
        if (d.getElementById(id)) return;
227
        js = d.createElement(s); js.id = id;
228
        js.src = "//connect.facebook.net/hr_HR/sdk.js#version=v2.0&xfbml=1&appId=";
229
        fjs.parentNode.insertBefore(js, fjs);
230
    }(document, 'script', 'facebook-jssdk'));</script>
231
    </script>
232
233
<script type='text/javascript' src='$siteurl/wp-content/plugins/ajax-load-more/core/js/ajax-load-more.min.js?ver=1.1'></script>
234
<script type='text/javascript' src='$siteurl/wp-content/plugins/wp-ga-social-tracking-js/ga-social-tracking.min.js'></script>
235
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/alm-seo.js'></script>
236
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/jquery.placeholder-2.1.1.min.js'></script>
237
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/typeahead.bundle.min.js'></script>
238
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/bootstrap-tagsinput.min.js'></script>
239
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/m-mobilemenu.js'></script>
240
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/main.js'></script>
241
<script type='text/javascript' src='$siteurl/wp-includes/js/comment-reply.min.js?ver=4.1.1'></script>
242
</body>
243
</html>
244
MARKUP;
245
246
        return $markup;
247
    }
248
249 View Code Duplication
    protected function get_test_markup_output()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
250
    {
251
        $key = 'default';
252
        if ( defined( 'CUSTOM_CONSTANTS_USED' ) && CUSTOM_CONSTANTS_USED ) {
253
            $key = 'custom';
254
        }
255
256
        $csspart = self::$flexible_url_parts_css[ $key ];
257
        $jspart  = self::$flexible_url_parts_js[ $key ];
258
259
        $csshash = '863f587e89f100b0223ddccc0dabc57a';
260
        if ( AO_TEST_SUBFOLDER_INSTALL ) {
261
            $csshash = '56398de576d59887e88e3011715250e0';
262
        }
263
264
        $urls      = $this->get_urls();
265
            $siteurl   = $urls['siteurl'];
266
        $cdnurl    = $urls['cdnurl'];
267
        $subfolder = $urls['subfolder'];
268
269
        $markup = <<<MARKUP
270
<!DOCTYPE html>
271
<!--[if lt IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8 lt-ie7"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
272
<!--[if IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
273
<!--[if IE 8]> <html class="no-svg no-js lt-ie9"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
274
<!--[if gt IE 8]><!--> <html class="no-svg no-js"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <!--<![endif]-->
275
<head>
276
<meta charset="utf-8">
277
<link media="all" href="${cdnurl}/${subfolder}${csspart}${csshash}.css" rel="stylesheet" /><title>Mliječna juha od brokule &#9832; Kuhaj.hr</title>
278
<meta name="viewport" content="width=device-width,initial-scale=1">
279
280
    <!--[if lt IE 9]>
281
    <script src="$siteurl/wp-content/themes/my-theme/js/vendor/html5shiv-printshiv.min.js" type="text/javascript"></script>
282
    <![endif]-->
283
    <!--[if (gte IE 6)&(lte IE 8)]>
284
        <script type="text/javascript" src="$siteurl/wp-content/themes/my-theme/js/vendor/respond.min.js"></script>
285
    <![endif]-->
286
</head>
287
288
<body class="single single-post">
289
290
    <div id="fb-root"></div>
291
    <script>(function(d, s, id) {
292
        var js, fjs = d.getElementsByTagName(s)[0];
293
        if (d.getElementById(id)) return;
294
        js = d.createElement(s); js.id = id;
295
        js.src = "//connect.facebook.net/hr_HR/sdk.js#version=v2.0&xfbml=1&appId=";
296
        fjs.parentNode.insertBefore(js, fjs);
297
    }(document, 'script', 'facebook-jssdk'));</script>
298
    </script>
299
300
<script type='text/javascript' src='$siteurl/wp-content/plugins/ajax-load-more/core/js/ajax-load-more.min.js?ver=1.1'></script>
301
<script type='text/javascript' src='$siteurl/wp-content/plugins/wp-ga-social-tracking-js/ga-social-tracking.min.js'></script>
302
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/alm-seo.js'></script>
303
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/jquery.placeholder-2.1.1.min.js'></script>
304
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/typeahead.bundle.min.js'></script>
305
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/bootstrap-tagsinput.min.js'></script>
306
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/m-mobilemenu.js'></script>
307
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/main.js'></script>
308
309
<script defer src="$cdnurl/${subfolder}${jspart}b3bc6ff617884cff344e049b95b2d3a0.js"></script></body>
310
</html>
311
MARKUP;
312
313
        return $markup;
314
    }
315
316 View Code Duplication
    protected function get_test_markup_output_ms()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
317
    {
318
        $key = 'multisite';
319
        if ( defined( 'CUSTOM_CONSTANTS_USED' ) && CUSTOM_CONSTANTS_USED ) {
320
            $key = 'multisite_custom';
321
        }
322
323
        $csspart = self::$flexible_url_parts_css[ $key ];
324
        $jspart  = self::$flexible_url_parts_js[ $key ];
325
326
        $csshash = '863f587e89f100b0223ddccc0dabc57a';
327
        if ( AO_TEST_SUBFOLDER_INSTALL ) {
328
            $csshash = '56398de576d59887e88e3011715250e0';
329
        }
330
331
        $urls      = $this->get_urls();
332
        $siteurl   = $urls['siteurl'];
333
        $cdnurl    = $urls['cdnurl'];
334
        $subfolder = $urls['subfolder'];
335
336
        $markup = <<<MARKUP
337
<!DOCTYPE html>
338
<!--[if lt IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8 lt-ie7"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
339
<!--[if IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
340
<!--[if IE 8]> <html class="no-svg no-js lt-ie9"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
341
<!--[if gt IE 8]><!--> <html class="no-svg no-js"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <!--<![endif]-->
342
<head>
343
<meta charset="utf-8">
344
<link media="all" href="$cdnurl/${subfolder}${csspart}${csshash}.css" rel="stylesheet" /><title>Mliječna juha od brokule &#9832; Kuhaj.hr</title>
345
<meta name="viewport" content="width=device-width,initial-scale=1">
346
347
    <!--[if lt IE 9]>
348
    <script src="$siteurl/wp-content/themes/my-theme/js/vendor/html5shiv-printshiv.min.js" type="text/javascript"></script>
349
    <![endif]-->
350
    <!--[if (gte IE 6)&(lte IE 8)]>
351
        <script type="text/javascript" src="$siteurl/wp-content/themes/my-theme/js/vendor/respond.min.js"></script>
352
    <![endif]-->
353
</head>
354
355
<body class="single single-post">
356
357
    <div id="fb-root"></div>
358
    <script>(function(d, s, id) {
359
        var js, fjs = d.getElementsByTagName(s)[0];
360
        if (d.getElementById(id)) return;
361
        js = d.createElement(s); js.id = id;
362
        js.src = "//connect.facebook.net/hr_HR/sdk.js#version=v2.0&xfbml=1&appId=";
363
        fjs.parentNode.insertBefore(js, fjs);
364
    }(document, 'script', 'facebook-jssdk'));</script>
365
    </script>
366
367
<script type='text/javascript' src='$siteurl/wp-content/plugins/ajax-load-more/core/js/ajax-load-more.min.js?ver=1.1'></script>
368
<script type='text/javascript' src='$siteurl/wp-content/plugins/wp-ga-social-tracking-js/ga-social-tracking.min.js'></script>
369
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/alm-seo.js'></script>
370
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/jquery.placeholder-2.1.1.min.js'></script>
371
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/typeahead.bundle.min.js'></script>
372
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/bootstrap-tagsinput.min.js'></script>
373
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/m-mobilemenu.js'></script>
374
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/main.js'></script>
375
376
<script defer src="$cdnurl/${subfolder}${jspart}b3bc6ff617884cff344e049b95b2d3a0.js"></script></body>
377
</html>
378
MARKUP;
379
380
        return $markup;
381
    }
382
383 View Code Duplication
    protected function get_test_markup_output_inline_defer()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
384
    {
385
        $key = 'default';
386
        if ( defined( 'CUSTOM_CONSTANTS_USED' ) && CUSTOM_CONSTANTS_USED ) {
387
            $key = 'custom';
388
        }
389
390
        $csspart = self::$flexible_url_parts_css[ $key ];
391
        $jspart  = self::$flexible_url_parts_js[ $key ];
392
393
        $csshash = '863f587e89f100b0223ddccc0dabc57a';
394
        if ( AO_TEST_SUBFOLDER_INSTALL ) {
395
            $csshash = '56398de576d59887e88e3011715250e0';
396
        }
397
398
        $urls      = $this->get_urls();
399
        $siteurl   = $urls['siteurl'];
400
        $cdnurl    = $urls['cdnurl'];
401
        $subfolder = $urls['subfolder'];
402
403
        $markup = <<<MARKUP
404
<!DOCTYPE html>
405
<!--[if lt IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8 lt-ie7"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
406
<!--[if IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
407
<!--[if IE 8]> <html class="no-svg no-js lt-ie9"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
408
<!--[if gt IE 8]><!--> <html class="no-svg no-js"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <!--<![endif]-->
409
<head>
410
<meta charset="utf-8">
411
<style id="aoatfcss" media="all">1</style><link rel="preload" as="style" media="all" href="$cdnurl/${subfolder}${csspart}{$csshash}.css" onload="this.onload=null;this.rel='stylesheet'" /><noscript id="aonoscrcss"><link media="all" href="$cdnurl/${subfolder}${csspart}${csshash}.css" rel="stylesheet" /></noscript><title>Mliječna juha od brokule &#9832; Kuhaj.hr</title>
412
<meta name="viewport" content="width=device-width,initial-scale=1">
413
414
    <!--[if lt IE 9]>
415
    <script src="$siteurl/wp-content/themes/my-theme/js/vendor/html5shiv-printshiv.min.js" type="text/javascript"></script>
416
    <![endif]-->
417
    <!--[if (gte IE 6)&(lte IE 8)]>
418
        <script type="text/javascript" src="$siteurl/wp-content/themes/my-theme/js/vendor/respond.min.js"></script>
419
    <![endif]-->
420
</head>
421
422
<body class="single single-post">
423
424
    <div id="fb-root"></div>
425
    <script>(function(d, s, id) {
426
        var js, fjs = d.getElementsByTagName(s)[0];
427
        if (d.getElementById(id)) return;
428
        js = d.createElement(s); js.id = id;
429
        js.src = "//connect.facebook.net/hr_HR/sdk.js#version=v2.0&xfbml=1&appId=";
430
        fjs.parentNode.insertBefore(js, fjs);
431
    }(document, 'script', 'facebook-jssdk'));</script>
432
    </script>
433
434
<script type='text/javascript' src='$siteurl/wp-content/plugins/ajax-load-more/core/js/ajax-load-more.min.js?ver=1.1'></script>
435
<script type='text/javascript' src='$siteurl/wp-content/plugins/wp-ga-social-tracking-js/ga-social-tracking.min.js'></script>
436
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/alm-seo.js'></script>
437
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/jquery.placeholder-2.1.1.min.js'></script>
438
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/typeahead.bundle.min.js'></script>
439
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/bootstrap-tagsinput.min.js'></script>
440
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/m-mobilemenu.js'></script>
441
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/main.js'></script>
442
443
<script defer src="$cdnurl/${subfolder}${jspart}b3bc6ff617884cff344e049b95b2d3a0.js"></script><script data-cfasync='false'>!function(t){"use strict";t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){function e(){t.media=a}var a=t.media||"all";t.addEventListener?t.addEventListener("load",e):t.attachEvent&&t.attachEvent("onload",e),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(e,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName("link"),n=0;n<a.length;n++){var o=a[n];"preload"!==o.rel||"style"!==o.getAttribute("as")||o.getAttribute("data-loadcss")||(o.setAttribute("data-loadcss",!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener("load",function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent("onload",function(){e.poly(),t.clearInterval(a)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}("undefined"!=typeof global?global:this);</script></body>
444
</html>
445
MARKUP;
446
447
        return $markup;
448
    }
449
450 View Code Duplication
    protected function get_test_markup_output_inline_defer_ms()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
451
    {
452
        $key = 'multisite';
453
        if ( defined( 'CUSTOM_CONSTANTS_USED' ) && CUSTOM_CONSTANTS_USED ) {
454
            $key = 'multisite_custom';
455
        }
456
457
        $csspart = self::$flexible_url_parts_css[ $key ];
458
        $jspart  = self::$flexible_url_parts_js[ $key ];
459
460
        $csshash = '863f587e89f100b0223ddccc0dabc57a';
461
        if ( AO_TEST_SUBFOLDER_INSTALL ) {
462
            $csshash = '56398de576d59887e88e3011715250e0';
463
        }
464
465
        $urls      = $this->get_urls();
466
        $siteurl   = $urls['siteurl'];
467
        $cdnurl    = $urls['cdnurl'];
468
        $subfolder = $urls['subfolder'];
469
470
        $markup = <<<MARKUP
471
<!DOCTYPE html>
472
<!--[if lt IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8 lt-ie7"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
473
<!--[if IE 7]> <html class="no-svg no-js lt-ie9 lt-ie8"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
474
<!--[if IE 8]> <html class="no-svg no-js lt-ie9"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <![endif]-->
475
<!--[if gt IE 8]><!--> <html class="no-svg no-js"  xmlns:fb="https://www.facebook.com/2008/fbml"  xmlns:og="http://ogp.me/ns#" lang="hr"> <!--<![endif]-->
476
<head>
477
<meta charset="utf-8">
478
<style id="aoatfcss" media="all">1</style><link rel="preload" as="style" media="all" href="$cdnurl/${subfolder}${csspart}${csshash}.css" onload="this.onload=null;this.rel='stylesheet'" /><noscript id="aonoscrcss"><link media="all" href="$cdnurl/${subfolder}${csspart}${csshash}.css" rel="stylesheet" /></noscript><title>Mliječna juha od brokule &#9832; Kuhaj.hr</title>
479
<meta name="viewport" content="width=device-width,initial-scale=1">
480
481
    <!--[if lt IE 9]>
482
    <script src="$siteurl/wp-content/themes/my-theme/js/vendor/html5shiv-printshiv.min.js" type="text/javascript"></script>
483
    <![endif]-->
484
    <!--[if (gte IE 6)&(lte IE 8)]>
485
        <script type="text/javascript" src="$siteurl/wp-content/themes/my-theme/js/vendor/respond.min.js"></script>
486
    <![endif]-->
487
</head>
488
489
<body class="single single-post">
490
491
    <div id="fb-root"></div>
492
    <script>(function(d, s, id) {
493
        var js, fjs = d.getElementsByTagName(s)[0];
494
        if (d.getElementById(id)) return;
495
        js = d.createElement(s); js.id = id;
496
        js.src = "//connect.facebook.net/hr_HR/sdk.js#version=v2.0&xfbml=1&appId=";
497
        fjs.parentNode.insertBefore(js, fjs);
498
    }(document, 'script', 'facebook-jssdk'));</script>
499
    </script>
500
501
<script type='text/javascript' src='$siteurl/wp-content/plugins/ajax-load-more/core/js/ajax-load-more.min.js?ver=1.1'></script>
502
<script type='text/javascript' src='$siteurl/wp-content/plugins/wp-ga-social-tracking-js/ga-social-tracking.min.js'></script>
503
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/alm-seo.js'></script>
504
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/jquery.placeholder-2.1.1.min.js'></script>
505
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/typeahead.bundle.min.js'></script>
506
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/vendor/bootstrap-tagsinput.min.js'></script>
507
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/m-mobilemenu.js'></script>
508
<script type='text/javascript' src='$siteurl/wp-content/themes/my-theme/js/main.js'></script>
509
510
<script defer src="$cdnurl/${subfolder}${jspart}b3bc6ff617884cff344e049b95b2d3a0.js"></script><script data-cfasync='false'>!function(t){"use strict";t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){function e(){t.media=a}var a=t.media||"all";t.addEventListener?t.addEventListener("load",e):t.attachEvent&&t.attachEvent("onload",e),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(e,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName("link"),n=0;n<a.length;n++){var o=a[n];"preload"!==o.rel||"style"!==o.getAttribute("as")||o.getAttribute("data-loadcss")||(o.setAttribute("data-loadcss",!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener("load",function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent("onload",function(){e.poly(),t.clearInterval(a)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}("undefined"!=typeof global?global:this);</script></body>
511
</html>
512
MARKUP;
513
514
        return $markup;
515
    }
516
517
    /**
518
     * @dataProvider provider_test_rewrite_markup_with_cdn
519
     */
520
    function test_rewrite_markup_with_cdn( $input, $expected )
521
    {
522
        $actual = $this->ao->end_buffering( $input );
523
524
        $this->assertEquals( $expected, $actual );
525
    }
526
527
    public function provider_test_rewrite_markup_with_cdn()
528
    {
529
        return array(
530
531
            array(
532
                // Input.
533
                $this->get_test_markup(),
534
                // Expected output.
535
                // TODO/FIXME: This seemed like the fastest way to get MS crude test to pass...
536
                ( is_multisite() ? $this->get_test_markup_output_ms() : $this->get_test_markup_output() ),
537
            ),
538
539
        );
540
    }
541
542
    public function test_rewrite_css_assets()
543
    {
544
        $urls   = $this->get_urls();
545
        $cdnurl = $urls['cdnurl'];
546
        $sub    = $urls['subfolder'];
547
548
        $css_in = <<<CSS
549
.bg { background:url('img/something.svg'); }
550
.bg-no-quote { background: url(img/something.svg); }
551
.bg-double-quotes { background: url("img/something.svg"); }
552
553
.whitespaces { background : url   (  "../../somewhere-else/svg.svg" ) ; }
554
555
.host-relative { background: url("/img/something.svg"); }
556
.protocol-relative { background: url("//something/somewhere/example.png"); }
557
558
@font-face {
559
  font-family: 'Roboto';
560
  font-style: normal;
561
  font-weight: 100;
562
  src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
563
  src: local('Roboto Thin'), local('Roboto-Thin'),
564
       url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
565
       url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
566
       url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
567
       url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
568
       url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
569
}
570
CSS;
571
572
        $css_expected = <<<CSS
573
.bg { background:url(img/something.svg); }
574
.bg-no-quote { background: url(img/something.svg); }
575
.bg-double-quotes { background: url(img/something.svg); }
576
577
.whitespaces { background : url   (  ../../somewhere-else/svg.svg) ; }
578
579
.host-relative { background: url(${cdnurl}/${sub}img/something.svg); }
580
.protocol-relative { background: url(//something/somewhere/example.png); }
581
582
@font-face {
583
  font-family: 'Roboto';
584
  font-style: normal;
585
  font-weight: 100;
586
  src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
587
  src: local('Roboto Thin'), local('Roboto-Thin'),
588
       url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
589
       url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
590
       url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
591
       url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
592
       url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
593
}
594
CSS;
595
596
        $instance = new autoptimizeStyles( $css_in );
597
        $instance->setOption( 'cdn_url', $cdnurl );
598
599
        $css_actual = $instance->rewrite_assets( $css_in );
600
601
        $this->assertEquals( $css_expected, $css_actual );
602
    }
603
604 View Code Duplication
    public function test_default_cssmin_minifier()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
605
    {
606
        $css = <<<CSS
607
.bg { background:url('img/something.svg'); }
608
.bg-no-quote { background: url(img/something.svg); }
609
.bg-double-quotes { background: url("img/something.svg"); }
610
611
.whitespaces { background : url   (  "../../somewhere-else/svg.svg" ) ; }
612
613
.host-relative { background: url("/img/something.svg"); }
614
.protocol-relative { background: url("//something/somewhere/example.png"); }
615
616
/* roboto-100 - latin-ext_latin */
617
@font-face {
618
  font-family: 'Roboto';
619
  font-style: normal;
620
  font-weight: 100;
621
  src: url(../fonts/roboto-v15-latin-ext_latin-100.eot); /* IE9 Compat Modes */
622
  src: local('Roboto Thin'), local('Roboto-Thin'),
623
       url(../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'), /* IE6-IE8 */
624
       url(../fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'), /* Super Modern Browsers */
625
       url(../fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'), /* Modern Browsers */
626
       url(../fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'), /* Safari, Android, iOS */
627
       url(../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg'); /* Legacy iOS */
628
}
629
CSS;
630
631
        $expected = <<<CSS
632
.bg{background:url('img/something.svg')}.bg-no-quote{background:url(img/something.svg)}.bg-double-quotes{background:url("img/something.svg")}.whitespaces{background:url ("../../somewhere-else/svg.svg")}.host-relative{background:url("/img/something.svg")}.protocol-relative{background:url("//something/somewhere/example.png")}@font-face{font-family:'Roboto';font-style:normal;font-weight:100;src:url(../fonts/roboto-v15-latin-ext_latin-100.eot);src:local('Roboto Thin'),local('Roboto-Thin'),url(../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'),url(../fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'),url(../fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'),url(../fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'),url(../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg')}
633
CSS;
634
635
        $instance = new autoptimizeStyles( $css );
636
        $minified = $instance->run_minifier_on( $css );
637
638
        $this->assertEquals( $expected, $minified );
639
    }
640
641
    /**
642
     * @dataProvider provider_test_should_aggregate_script_types
643
     */
644
    public function test_should_aggregate_script_types( $input, $expected )
645
    {
646
        $instance = new autoptimizeScripts( '' );
647
        $actual   = $instance->should_aggregate( $input );
648
649
        $this->assertEquals( $expected, $actual );
650
    }
651
652
    public function provider_test_should_aggregate_script_types()
653
    {
654
        return array(
655
            // No type attribute at all.
656
            array(
657
                // Input.
658
                '<script>var something=true</script>',
659
                // Expected output.
660
                true,
661
            ),
662
            // Case-insensitive.
663
            array(
664
                '<script type="text/ecmaScript">var something=true</script>',
665
                true,
666
            ),
667
            // Allowed/aggregated now (wasn't previously).
668
            array(
669
                '<script type="application/javascript">var something=true</script>',
670
                true,
671
            ),
672
            // Quotes shouldn't matter, nor should case-sensitivity.
673
            array(
674
                '<script type=\'text/JaVascriPt">var something=true</script>',
675
                true,
676
            ),
677
            // Liberal to whitespace around attribute names/values.
678
            array(
679
                '<script tYpe = text/javascript>var something=true</script>',
680
                true,
681
            ),
682
            // Something custom, should be ignored/skipped.
683
            array(
684
                '<script type=template/javascript>var something=true</script>',
685
                false,
686
            ),
687
            // Type attribute checking should be constrained to actual script
688
            // tag's type attribute only, regardless of any `type=` string
689
            // present in the actual inline script contents.
690
            array(
691
                // Since there's no type attribute, it should be aggregate by default.
692
                '<script>var type=something;</script>',
693
                true,
694
            ),
695
            // Application/ld+json should not be aggregated by default regardless
696
            // of spacing around attr/values.
697
            array(
698
                '<script type = "application/ld+json" >{   "@context": "" }',
699
                false,
700
            ),
701
            array(
702
                '<script type="application/ld+json">{   "@context": "" }',
703
                false,
704
            ),
705
        );
706
    }
707
708
    /**
709
     * @dataProvider provider_is_valid_buffer
710
     */
711
    public function test_valid_buffers( $input, $expected )
712
    {
713
        $actual = $this->ao->is_valid_buffer( $input );
714
715
        $this->assertEquals( $expected, $actual );
716
    }
717
718
    public function provider_is_valid_buffer()
719
    {
720
        return array(
721
            array(
722
                '<!doctype html>
723
<html ⚡>',
724
                false,
725
            ),
726
            array(
727
                '<!doctype html>
728
<html amp>',
729
                false,
730
            ),
731
            array(
732
                '<?xml version="1.0" encoding="UTF-8"?>
733
<xsl:stylesheet version="1.0"
734
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
735
                false,
736
            ),
737
            array(
738
                // adding doctype & html tags to make sure that this is falsed by the extended has_xsl_stylesheet test.
739
                '<?xml version="2.0" encoding="UTF-8"?>
740
<!doctype html><html>
741
<?xml-stylesheet type="text/xsl" ',
742
                false,
743
            ),
744
            array(
745
                '<!doctype html>
746
<html>',
747
                true,
748
            ),
749
            array(
750
                '<html dir="ltr" amp>',
751
                false,
752
            ),
753
            array(
754
                '<html dir="ltr" ⚡>',
755
                false,
756
            ),
757
            array(
758
                '<html amp dir="ltr">',
759
                false,
760
            ),
761
            array(
762
                '<html ⚡ dir="ltr">',
763
                false,
764
            ),
765
            array(
766
                '<HTML ⚡ DIR="LTR">',
767
                false,
768
            ),
769
            array(
770
                '<HTML AMP DIR="LTR">',
771
                false,
772
            ),
773
            // @link https://github.com/futtta/autoptimize/commit/54385939db06f725fcafe68598cce6ed148ef6c1
774
            array(
775
                '<!doctype html>',
776
                true,
777
            ),
778
        );
779
    }
780
781
    /**
782
     * @dataProvider provider_is_amp_markup
783
     */
784
    public function test_autoptimize_is_amp_markup( $input, $expected )
785
    {
786
        $actual = autoptimizeMain::is_amp_markup( $input );
787
788
        $this->assertEquals( $expected, $actual );
789
    }
790
791
    public function provider_is_amp_markup()
792
    {
793
        return array(
794
            array(
795
                '<!doctype html>
796
<html ⚡>',
797
                true,
798
            ),
799
            array(
800
                '<!doctype html>
801
<html amp>',
802
                true,
803
            ),
804
            array(
805
                '<!doctype html>
806
<head>
807
<meta charset=utf-8>',
808
                false,
809
            ),
810
        );
811
    }
812
813
    /**
814
     * Test various conditions that can/should prevent autoptimize from buffering content.
815
     */
816 View Code Duplication
    public function test_skips_buffering_when_ao_noptimize_filter_is_true()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
817
    {
818
        // True => disable autoptimize.
819
        add_filter( 'autoptimize_filter_noptimize', '__return_true' );
820
821
        // Buffering should not run due to the above filter.
822
        $expected = false;
823
        $actual   = $this->ao->should_buffer( $doing_tests = true );
824
825
        $this->assertEquals( $expected, $actual );
826
    }
827
828 View Code Duplication
    public function test_does_buffering_when_ao_noptimize_filter_is_false()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
829
    {
830
        // False => disable noptimize, aka, run normally (weird, yes...).
831
        add_filter( 'autoptimize_filter_noptimize', '__return_false' );
832
833
        // Buffering should run because of above.
834
        $expected = true;
835
        $actual   = $this->ao->should_buffer( $doing_tests = true );
836
837
        $this->assertEquals( $expected, $actual );
838
    }
839
840
    public function test_ignores_ao_noptimize_qs_when_instructed()
841
    {
842
        // Should skip checking for the qs completely due to filter.
843
        add_filter( 'autoptimize_filter_honor_qs_noptimize', '__return_false' );
844
845
        /**
846
         * The above should then result in the "current" value being `false`
847
         * when passed to 'autoptimize_filter_noptimize' unless the DONOTMINIFY
848
         * constant is defined, which changes the result... Which basically
849
         * means this test changes its' expected result depending on the order
850
         * of tests execution and/or the environment, which is AAAARGGGGGGHHH...
851
         */
852
853
        $that = $this; // Makes it work on php 5.3!
854
        add_filter( 'autoptimize_filter_noptimize', function ( $current_value ) use ( $that ) {
855
            $expected = false;
856
            if ( defined( 'DONOTMINIFY' ) && DONOTMINIFY ) {
857
                $expected = true;
858
            }
859
860
            $that->assertEquals( $expected, $current_value );
861
        });
862
863
        $this->ao->should_buffer( $doing_tests = true );
864
    }
865
866
    public function test_wpengine_cache_flush()
867
    {
868
        // Creating a mock so that we can get past class_exists() and method_exists() checks present
869
        // in `autoptimizeCache::flushPageCache()`...
870
        $stub = $this->getMockBuilder( 'WpeCommon' )->disableAutoload()
0 ignored issues
show
Unused Code introduced by
$stub is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
871
                ->disableOriginalConstructor()->setMethods(
872
                    array(
873
                        'purge_varnish_cache',
874
                    )
875
                )
876
                ->getMock();
877
878
        $that = $this;
879
        add_filter( 'autoptimize_flush_wpengine_methods', function( $methods ) use ( $that ) {
880
            $expected_methods = array( 'purge_varnish_cache' );
881
            $that->assertEquals( $methods, $expected_methods );
882
883
            return $methods;
884
        });
885
886
        autoptimizeCache::flushPageCache();
887
    }
888
889
    /**
890
     * Tests the `autoptimize_flush_wpengine_aggressive` filter
891
     */
892
    public function test_wpengine_cache_flush_agressive()
893
    {
894
        // Creating a mock so that we can get past class_exists() and method_exists() checks `autoptimize_flush_pagecache()`...
895
        $stub = $this->getMockBuilder( 'WpeCommon' )->disableAutoload()
0 ignored issues
show
Unused Code introduced by
$stub is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
896
                ->disableOriginalConstructor()->setMethods(
897
                    array(
898
                        'purge_varnish_cache',
899
                        'purge_memcached',
900
                        'clear_maxcdn_cache',
901
                    )
902
                )
903
                ->getMock();
904
905
        add_filter( 'autoptimize_flush_wpengine_aggressive', function() {
906
            return true;
907
        });
908
909
        $that = $this;
910
        add_filter( 'autoptimize_flush_wpengine_methods', function( $methods ) use ( $that ) {
911
            $expected_methods = array(
912
                'purge_varnish_cache',
913
                'purge_memcached',
914
                'clear_maxcdn_cache',
915
            );
916
917
            $that->assertEquals( $methods, $expected_methods );
918
919
            return $methods;
920
        });
921
922
        autoptimizeCache::flushPageCache();
923
    }
924
925
    /**
926
     * @dataProvider provider_test_url_replace_cdn
927
     */
928
    public function test_url_replace_cdn( $cdn_url, $input, $expected )
929
    {
930
        $mock = $this->getMockBuilder( 'autoptimizeBase' )
931
                ->disableOriginalConstructor()
932
                ->getMockForAbstractClass();
933
934
        $mock->cdn_url = $cdn_url;
935
        $actual        = $mock->url_replace_cdn( $input );
936
        $this->assertEquals( $expected, $actual );
937
    }
938
939
    public function provider_test_url_replace_cdn()
940
    {
941
        $urls                 = $this->get_urls();
942
        $siteurl              = $urls['siteurl'];
943
        $wwwsiteurl           = $urls['wwwsiteurl'];
944
        $protorelativesiteurl = $urls['prsiteurl'];
945
        $subfolder            = $urls['subfolder'];
946
947
        return array(
948
            // Host-relative links get properly transformed...
949
            array(
950
                // CDN base url, url, expected result...
951
                'http://cdn-test.example.org',
952
                '/a.jpg',
953
                'http://cdn-test.example.org/' . $subfolder . 'a.jpg',
954
            ),
955
            // Full link with a matching AUTOPTIMIZE_WP_SITE_URL gets properly replaced...
956
            array(
957
                'http://cdn-test.example.org',
958
                $siteurl . '/wp-content/themes/something/example.svg',
959
                'http://cdn-test.example.org/' . $subfolder . 'wp-content/themes/something/example.svg',
960
            ),
961
            // Protocol-relative url with a "local" hostname that doesn't match example.org (AUTOPTIMIZE_WP_SITE_URL)...
962
            array(
963
                'http://cdn-test.example.org',
964
                '//something/somewhere.jpg',
965
                '//something/somewhere.jpg',
966
            ),
967
            // www.example.org does not match example.org (AUTOPTIMIZE_WP_SITE_URL) so it's left alone...
968
            array(
969
                'http://cdn-test.example.org',
970
                $wwwsiteurl . '/wp-content/themes/something/example.svg',
971
                $wwwsiteurl . '/wp-content/themes/something/example.svg',
972
            ),
973
            // SSL cdn url + host-relative link...
974
            array(
975
                'https://cdn.example.org',
976
                '/a.jpg',
977
                'https://cdn.example.org/' . $subfolder . 'a.jpg',
978
            ),
979
            // SSL cdn url + http site url that matches AUTOPTIMIZE_WP_SITE_URL is properly replaced...
980
            array(
981
                'https://cdn.example.org',
982
                $siteurl . '/wp-content/themes/something/example.svg',
983
                'https://cdn.example.org/' . $subfolder . 'wp-content/themes/something/example.svg',
984
            ),
985
            // Protocol-relative cdn url given with protocol relative link that matches AUTOPTIMIZE_WP_SITE_URL host...
986
            array(
987
                '//cdn.example.org',
988
                $protorelativesiteurl . '/something.jpg',
989
                '//cdn.example.org/' . $subfolder . 'something.jpg',
990
            ),
991
            // Protocol-relative cdn url given a http link that matches AUTOPTIMIZE_WP_SITE_URL host...
992
            array(
993
                '//cdn.example.org',
994
                $siteurl . '/something.png',
995
                '//cdn.example.org/' . $subfolder . 'something.png',
996
            ),
997
            // Protocol-relative cdn url with a host-relative link...
998
            array(
999
                '//cdn.example.org',
1000
                '/a.jpg',
1001
                '//cdn.example.org/' . $subfolder . 'a.jpg',
1002
            ),
1003
            // Testing cdn urls with an explicit port number...
1004
            array(
1005
                'http://cdn.com:8080',
1006
                '/a.jpg',
1007
                'http://cdn.com:8080/' . $subfolder . 'a.jpg',
1008
            ),
1009
            array(
1010
                '//cdn.com:4433',
1011
                '/a.jpg',
1012
                '//cdn.com:4433/' . $subfolder . 'a.jpg',
1013
            ),
1014
            array(
1015
                '//cdn.com:4433',
1016
                $siteurl . '/something.jpg',
1017
                '//cdn.com:4433/' . $subfolder . 'something.jpg',
1018
            ),
1019
            array(
1020
                '//cdn.com:1234',
1021
                $protorelativesiteurl . '/something.jpg',
1022
                '//cdn.com:1234/' . $subfolder . 'something.jpg',
1023
            ),
1024
            // Relative links should not be touched by url_replace_cdn()...
1025
            array(
1026
                // Base cdn url.
1027
                'http://cdn-test.example.org',
1028
                // Url.
1029
                'a.jpg',
1030
                // Expected result.
1031
                'a.jpg',
1032
            ),
1033
            array(
1034
                'http://cdn-test.example.org',
1035
                './a.jpg',
1036
                './a.jpg',
1037
            ),
1038
            array(
1039
                'http://cdn-test.example.org',
1040
                '../something/somewhere.svg',
1041
                '../something/somewhere.svg',
1042
            ),
1043
            // These prove some weird combinations pre-2.4 remain working
1044
            // even though they are really strange...
1045
            array(
1046
                $siteurl, // example.org or http://localhost or http://localhost/wordpress
1047
                $siteurl . '/something.jpg',
1048
                $siteurl . '/something.jpg',
1049
            ),
1050
            // These shouldn't really be changed, or even if replacements do
1051
            // happen, they shouldn't be destructive...
1052
            array(
1053
                'http://localhost/wp',
1054
                'http://localhost/wp/something.jpg',
1055
                'http://localhost/wp/something.jpg',
1056
            ),
1057
            array(
1058
                'http://localhost',
1059
                'http://localhost/something.jpg',
1060
                'http://localhost/something.jpg',
1061
            ),
1062
            array(
1063
                'http://localhost',
1064
                'http://localhost/wordpress/something.jpg',
1065
                'http://localhost/wordpress/something.jpg',
1066
            ),
1067
            array(
1068
                'http://localhost/wordpress',
1069
                'http://localhost/wordpress/something.jpg',
1070
                'http://localhost/wordpress/something.jpg',
1071
            ),
1072
        );
1073
    }
1074
1075
    /**
1076
     * Tests `autoptimize_filter_base_cdnurl` filtering as described here:
1077
     * https://wordpress.org/support/topic/disable-cdn-of-ssl-pages
1078
     */
1079
    public function test_autoptimize_filter_base_cdnurl()
1080
    {
1081
        $urls = $this->get_urls();
1082
        $sub  = $urls['subfolder'];
1083
1084
        $test_link = '/a.jpg';
1085
        $cdn_url   = '//cdn.example.org';
1086
1087
        $with_ssl = function( $cdn ) {
0 ignored issues
show
Unused Code introduced by
The parameter $cdn is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1088
            return '';
1089
        };
1090
        $expected_with_ssl = '/a.jpg';
1091
1092
        $without_ssl = function( $cdn ) {
1093
            return $cdn;
1094
        };
1095
        $expected_without_ssl = '//cdn.example.org/' . $sub . 'a.jpg';
1096
1097
        // With a filter that returns something considered "empty", cdn replacement shouldn't occur...
1098
        add_filter( 'autoptimize_filter_base_cdnurl', $with_ssl );
1099
        $mock = $this->getMockBuilder( 'autoptimizeBase' )
1100
                ->disableOriginalConstructor()
1101
                ->getMockForAbstractClass();
1102
1103
        $mock->cdn_url   = $cdn_url;
1104
        $actual_with_ssl = $mock->url_replace_cdn( $test_link );
1105
        $this->assertEquals( $expected_with_ssl, $actual_with_ssl );
1106
        remove_filter( 'autoptimize_filter_base_cdnurl', $with_ssl );
1107
1108
        // With a filter that returns an actual cdn url, cdn replacement should occur.
1109
        add_filter( 'autoptimize_filter_base_cdnurl', $without_ssl );
1110
        $actual_without_ssl = $mock->url_replace_cdn( $test_link );
1111
        $this->assertEquals( $expected_without_ssl, $actual_without_ssl );
1112
    }
1113
1114
    public function provider_cssmin_issues()
1115
    {
1116
        return array(
1117
            // @link https://wordpress.org/support/topic/css-minify-breaks-calc-subtract-operation-in-css/?replies=2#post-6610027
1118
            array(
1119
                // Input.
1120
                'input { width: calc(33.33333% - ((0.75em*2)/3)); }',
1121
                // Expected output (ancient version of CSSmin returns 0.75, newer versions drop the 0).
1122
                'input{width:calc(33.33333% - ((.75em*2)/3))}',
1123
            ),
1124
            // Actual examples from above, but original wasn't really valid
1125
            // css input fully, but these tests used to work and we'd like to
1126
            // know if output changes with various CSSmin versions, for
1127
            // backcompat reasons if nothing else.
1128
            array(
1129
                // Input.
1130
                'width: calc(33.33333% - ((0.75em*2)/3));',
1131
                // Expected output.
1132
                'width:calc(33.33333% - ((0.75em*2)/3));',
1133
            ),
1134
            // @link https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port/issues/22#issuecomment-251401341
1135
            array(
1136
                'input { width: calc(100% - (1em*1.5) - 2em); }',
1137
                'input{width:calc(100% - (1em*1.5) - 2em)}',
1138
            ),
1139
            // @link https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port/issues/26
1140
            array(
1141
                '.px { flex: 1 1 0px; }, .percent {flex: 1 1 0%}',
1142
                '.px{flex:1 1 0px},.percent{flex:1 1 0%}',
1143
            ),
1144
        );
1145
    }
1146
1147
    /**
1148
     * @dataProvider provider_cssmin_issues
1149
     */
1150
    public function test_cssmin_issues( $input, $expected )
1151
    {
1152
        $minifier = new autoptimizeCSSmin( false ); // No need to raise limits for now.
1153
        $actual   = $minifier->run( $input );
1154
        $this->assertEquals( $expected, $actual );
1155
    }
1156
1157
    public function provider_getpath()
1158
    {
1159
        return array(
1160
            /**
1161
             * These all don't really exist, and getpath() returns false for
1162
             * non-existing files since upstream's 1386e4fe1d commit.
1163
             */
1164
            array(
1165
                'img/something.svg',
1166
                false,
1167
            ),
1168
            array(
1169
                '../../somewhere-else/svg.svg',
1170
                false,
1171
            ),
1172
            array(
1173
                '//something/somewhere/example.png',
1174
                false,
1175
            ),
1176
            // This file comes with core, so should exist...
1177
            array(
1178
                '/wp-includes/js/jquery/jquery.js',
1179
                WP_ROOT_DIR . '/wp-includes/js/jquery/jquery.js',
1180
            ),
1181
            // Empty $url should return false.
1182
            array(
1183
                '',
1184
                false,
1185
            ),
1186
            array(
1187
                false,
1188
                false,
1189
            ),
1190
            array(
1191
                null,
1192
                false,
1193
            ),
1194
            array(
1195
                0,
1196
                false,
1197
            ),
1198
        );
1199
    }
1200
1201
    /**
1202
     * @dataProvider provider_getpath
1203
     */
1204
    public function test_getpath( $input, $expected )
1205
    {
1206
        $mock = $this->getMockBuilder( 'autoptimizeBase' )->disableOriginalConstructor()->getMockForAbstractClass();
1207
1208
        $actual = $mock->getpath( $input );
1209
        $this->assertEquals( $expected, $actual );
1210
    }
1211
1212
    /**
1213
     * @link https://github.com/futtta/autoptimize/pull/81#issuecomment-278935307
1214
     */
1215
    public function test_fixurls_with_hash_only_urls()
1216
    {
1217
        $urls      = $this->get_urls();
1218
        $siteurl   = $urls['siteurl'];
0 ignored issues
show
Unused Code introduced by
$siteurl is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1219
        $subfolder = $urls['subfolder'];
0 ignored issues
show
Unused Code introduced by
$subfolder is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1220
1221
        $protorelativesiteurl = $urls['prsiteurl'];
1222
1223
        $css_orig     = <<<CSS
1224
header{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90px' height='110px' viewBox='0 0 90 110'%3E%3Cstyle%3E.a%7Bstop-color:%23FFF;%7D.b%7Bstop-color:%23B2D235;%7D.c%7Bstop-color:%23BEE7FA;%7D.d%7Bfill:%23590C15;%7D%3C/style%3E%3ClinearGradient id='c' y2='135.4' gradientUnits='userSpaceOnUse' x2='209.1' gradientTransform='rotate(-1.467 -4082.888 7786.794)' y1='205.8' x1='262'%3E%3Cstop class='b' offset='0'/%3E%3Cstop class='b' offset='.48'/%3E%3Cstop stop-color='%23829D25' offset='1'/%3E%3C/linearGradient%3E%3Cpath stroke-width='.3' d='M77.3 45.4c-3-3.5-7.1-6.5-11.6-7.8-5.1-1.5-10-.1-14.9 1.5C52 35.4 54.3 29 60 24l-4.8-5.5c-3.4 3-5.8 6.3-7.5 9.4-1.7-4.3-4.1-8.4-7.5-12C33.4 8.6 24.3 4.7 15.1 4.2c-.2 9.3 3.1 18.6 9.9 25.9 5.2 5.6 11.8 9.2 18.7 10.8-2.5.2-4.9-.1-7.7-.9-5.2-1.4-10.5-2.8-15.8-1C10.6 42.3 4.5 51.9 4 61.7c-.5 11.6 3.8 23.8 9.9 33.5 3.9 6.3 9.6 13.7 17.7 13.4 3.8-.1 7-2.1 10.7-2.7 5.2-.8 9.1 1.2 14.1 1.8 16.4 2 24.4-23.6 26.4-35.9 1.2-9.1.8-19.1-5.5-26.4z' stroke='%233E6D1F' fill='url(%23c)'/%3E%3C/svg%3E")}
1225
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1226
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1227
.myimg {background-image: url("images/under-left-leaf.png"), url("images/over-blue-bird.png"), url("images/under-top.png"), url("images/bg-top-grunge.png");}
1228
CSS;
1229
        $css_expected = <<<CSS
1230
header{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90px' height='110px' viewBox='0 0 90 110'%3E%3Cstyle%3E.a%7Bstop-color:%23FFF;%7D.b%7Bstop-color:%23B2D235;%7D.c%7Bstop-color:%23BEE7FA;%7D.d%7Bfill:%23590C15;%7D%3C/style%3E%3ClinearGradient id='c' y2='135.4' gradientUnits='userSpaceOnUse' x2='209.1' gradientTransform='rotate(-1.467 -4082.888 7786.794)' y1='205.8' x1='262'%3E%3Cstop class='b' offset='0'/%3E%3Cstop class='b' offset='.48'/%3E%3Cstop stop-color='%23829D25' offset='1'/%3E%3C/linearGradient%3E%3Cpath stroke-width='.3' d='M77.3 45.4c-3-3.5-7.1-6.5-11.6-7.8-5.1-1.5-10-.1-14.9 1.5C52 35.4 54.3 29 60 24l-4.8-5.5c-3.4 3-5.8 6.3-7.5 9.4-1.7-4.3-4.1-8.4-7.5-12C33.4 8.6 24.3 4.7 15.1 4.2c-.2 9.3 3.1 18.6 9.9 25.9 5.2 5.6 11.8 9.2 18.7 10.8-2.5.2-4.9-.1-7.7-.9-5.2-1.4-10.5-2.8-15.8-1C10.6 42.3 4.5 51.9 4 61.7c-.5 11.6 3.8 23.8 9.9 33.5 3.9 6.3 9.6 13.7 17.7 13.4 3.8-.1 7-2.1 10.7-2.7 5.2-.8 9.1 1.2 14.1 1.8 16.4 2 24.4-23.6 26.4-35.9 1.2-9.1.8-19.1-5.5-26.4z' stroke='%233E6D1F' fill='url(%23c)'/%3E%3C/svg%3E")}
1231
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1232
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1233
.myimg {background-image: url($protorelativesiteurl/wp-content/themes/my-theme/images/under-left-leaf.png), url($protorelativesiteurl/wp-content/themes/my-theme/images/over-blue-bird.png), url($protorelativesiteurl/wp-content/themes/my-theme/images/under-top.png), url($protorelativesiteurl/wp-content/themes/my-theme/images/bg-top-grunge.png);}
1234
CSS;
1235
1236
        $fixurls_result = autoptimizeStyles::fixurls( ABSPATH . 'wp-content/themes/my-theme/style.css', $css_orig );
1237
        $this->assertEquals( $css_expected, $fixurls_result );
1238
    }
1239
1240
    public function test_background_datauri_sprites_with_fixurls()
1241
    {
1242
        $css_orig     = <<<CSS
1243
.shadow { background:url(img/1x1.png) top center; }
1244
.shadow1 { background-image:url(img/1x1.png) 0 -767px repeat-x; }
1245
.shadow2 {background:url(img/1x1.png) top center}
1246
1247
.test { background:url(img/1x1.png) top center; }
1248
.test1 { background-image:url('img/1x1.png') 0 -767px repeat-x; }
1249
.test2 {background:url("img/1x1.png") top center}
1250
1251
header{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90px' height='110px' viewBox='0 0 90 110'%3E%3Cstyle%3E.a%7Bstop-color:%23FFF;%7D.b%7Bstop-color:%23B2D235;%7D.c%7Bstop-color:%23BEE7FA;%7D.d%7Bfill:%23590C15;%7D%3C/style%3E%3ClinearGradient id='c' y2='135.4' gradientUnits='userSpaceOnUse' x2='209.1' gradientTransform='rotate(-1.467 -4082.888 7786.794)' y1='205.8' x1='262'%3E%3Cstop class='b' offset='0'/%3E%3Cstop class='b' offset='.48'/%3E%3Cstop stop-color='%23829D25' offset='1'/%3E%3C/linearGradient%3E%3Cpath stroke-width='.3' d='M77.3 45.4c-3-3.5-7.1-6.5-11.6-7.8-5.1-1.5-10-.1-14.9 1.5C52 35.4 54.3 29 60 24l-4.8-5.5c-3.4 3-5.8 6.3-7.5 9.4-1.7-4.3-4.1-8.4-7.5-12C33.4 8.6 24.3 4.7 15.1 4.2c-.2 9.3 3.1 18.6 9.9 25.9 5.2 5.6 11.8 9.2 18.7 10.8-2.5.2-4.9-.1-7.7-.9-5.2-1.4-10.5-2.8-15.8-1C10.6 42.3 4.5 51.9 4 61.7c-.5 11.6 3.8 23.8 9.9 33.5 3.9 6.3 9.6 13.7 17.7 13.4 3.8-.1 7-2.1 10.7-2.7 5.2-.8 9.1 1.2 14.1 1.8 16.4 2 24.4-23.6 26.4-35.9 1.2-9.1.8-19.1-5.5-26.4z' stroke='%233E6D1F' fill='url(%23c)'/%3E%3C/svg%3E")}
1252
1253
/*
1254
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1255
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1256
.myimg {background-image: url("images/under-left-leaf.png"), url("images/over-blue-bird.png"), url("images/under-top.png"), url("images/bg-top-grunge.png");}
1257
.something {
1258
    background:url(http://example.org/wp-content/themes/my-theme/images/nothing.png);
1259
}
1260
.something-else {background:url(wp-content/themes/my-theme/images/shadow.png) -100px 0 repeat-y;}
1261
.another-thing { background:url(/wp-content/themes/my-theme/images/shadow.png) 0 -767px repeat-x; }
1262
#whatevz {background:url(wp-content/themes/my-theme/images/shadow.png) center top no-repeat;}
1263
1264
.widget ul li { background:url(img/shadow.png) top center; }
1265
*/
1266
CSS;
1267
        $css_expected = <<<CSS
1268
.shadow { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1269
.shadow1 { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1270
.shadow2 {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center}
1271
1272
.test { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1273
.test1 { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1274
.test2 {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center}
1275
1276
header{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90px' height='110px' viewBox='0 0 90 110'%3E%3Cstyle%3E.a%7Bstop-color:%23FFF;%7D.b%7Bstop-color:%23B2D235;%7D.c%7Bstop-color:%23BEE7FA;%7D.d%7Bfill:%23590C15;%7D%3C/style%3E%3ClinearGradient id='c' y2='135.4' gradientUnits='userSpaceOnUse' x2='209.1' gradientTransform='rotate(-1.467 -4082.888 7786.794)' y1='205.8' x1='262'%3E%3Cstop class='b' offset='0'/%3E%3Cstop class='b' offset='.48'/%3E%3Cstop stop-color='%23829D25' offset='1'/%3E%3C/linearGradient%3E%3Cpath stroke-width='.3' d='M77.3 45.4c-3-3.5-7.1-6.5-11.6-7.8-5.1-1.5-10-.1-14.9 1.5C52 35.4 54.3 29 60 24l-4.8-5.5c-3.4 3-5.8 6.3-7.5 9.4-1.7-4.3-4.1-8.4-7.5-12C33.4 8.6 24.3 4.7 15.1 4.2c-.2 9.3 3.1 18.6 9.9 25.9 5.2 5.6 11.8 9.2 18.7 10.8-2.5.2-4.9-.1-7.7-.9-5.2-1.4-10.5-2.8-15.8-1C10.6 42.3 4.5 51.9 4 61.7c-.5 11.6 3.8 23.8 9.9 33.5 3.9 6.3 9.6 13.7 17.7 13.4 3.8-.1 7-2.1 10.7-2.7 5.2-.8 9.1 1.2 14.1 1.8 16.4 2 24.4-23.6 26.4-35.9 1.2-9.1.8-19.1-5.5-26.4z' stroke='%233E6D1F' fill='url(%23c)'/%3E%3C/svg%3E")}
1277
1278
/*
1279
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1280
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1281
.myimg {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=);}
1282
.something {
1283
    background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=);
1284
}
1285
.something-else {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) -100px 0 repeat-y;}
1286
.another-thing { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1287
#whatevz {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) center top no-repeat;}
1288
1289
.widget ul li { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1290
*/
1291
CSS;
1292
1293
        // For test purposes, ALL images in the css are being inline with a 1x1 trans png string/datauri.
1294
        add_filter( 'autoptimize_filter_css_is_datauri_candidate', function( $is_candidate, $path ) {
0 ignored issues
show
Unused Code introduced by
The parameter $is_candidate is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1295
            return true;
1296
        }, 10, 2 );
1297
1298
        // For test purposes, ALL images in the css are being inline with a 1x1 trans png string/datauri.
1299 View Code Duplication
        add_filter( 'autoptimize_filter_css_datauri_image', function( $base64array, $path ) {
0 ignored issues
show
Unused Code introduced by
The parameter $base64array is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1300
            $head = 'data:image/png;base64,';
1301
            $data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
1302
1303
            $result['full']       = $head . $data;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1304
            $result['base64data'] = $data;
1305
            return $result;
1306
        }, 10, 2 );
1307
1308
        $instance = new autoptimizeStyles( $css_orig );
1309
        $instance->setOption( 'datauris', true );
1310
1311
        $fixurls_result = autoptimizeStyles::fixurls( ABSPATH . 'wp-content/themes/my-theme/style.css', $css_orig );
1312
        $css_actual     = $instance->rewrite_assets( $fixurls_result );
1313
1314
        $this->assertEquals( $css_expected, $css_actual );
1315
    }
1316
1317
    /**
1318
     * Doing rewrite_assets() without calling fixurls() beforehand could
1319
     * cause wrong results if/when there's a (same) image referenced via
1320
     * root-relative and relative urls, i.e.,
1321
     * `/wp-content/themes/my-theme/images/shadow.png` and
1322
     * `wp-content/themes/my-theme/images/shadow.png` in test code below.
1323
     * That's because urls are not really "normalized" in rewrite_assets() at
1324
     * all, and replacements are done using simple string keys (based on url),
1325
     * so whenever the shorter url ends up being spotted first, the replacement
1326
     * was done in a way that leaves the first `/` character in place.
1327
     * Which could mean trouble, especially when doing inlining of smaller
1328
     * images.
1329
     * After sorting the replacements array in rewrite_assets() by string
1330
     * length in descending order, the problem goes away.
1331
     */
1332
    public function test_background_datauri_sprites_without_fixurls()
1333
    {
1334
        $css_orig     = <<<CSS
1335
.shadow { background:url(img/1x1.png) top center; }
1336
.shadow1 { background-image:url(img/1x1.png) 0 -767px repeat-x; }
1337
.shadow2 {background:url(img/1x1.png) top center}
1338
1339
.test { background:url(img/1x1.png) top center; }
1340
.test1 { background-image:url('img/1x1.png') 0 -767px repeat-x; }
1341
.test2 {background:url("img/1x1.png") top center}
1342
1343
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1344
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1345
.myimg {background-image: url("images/under-left-leaf.png"), url("images/over-blue-bird.png"), url("images/under-top.png"), url("images/bg-top-grunge.png");}
1346
.something {
1347
    background:url(http://example.org/wp-content/themes/my-theme/images/nothing.png);
1348
}
1349
.something-else {background:url(wp-content/themes/my-theme/images/shadow.png) -100px 0 repeat-y;}
1350
.another-thing { background:url(/wp-content/themes/my-theme/images/shadow.png) 0 -767px repeat-x; }
1351
#whatevz {background:url(wp-content/themes/my-theme/images/shadow.png) center top no-repeat;}
1352
1353
.widget ul li { background:url(img/shadow.png) top center; }
1354
CSS;
1355
        $css_expected = <<<CSS
1356
.shadow { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1357
.shadow1 { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1358
.shadow2 {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center}
1359
1360
.test { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1361
.test1 { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1362
.test2 {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center}
1363
1364
section.clipped.clippedTop {clip-path:url("#clipPolygonTop")}
1365
section.clipped.clippedBottom {clip-path:url("#clipPolygonBottom")}
1366
.myimg {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=);}
1367
.something {
1368
    background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=);
1369
}
1370
.something-else {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) -100px 0 repeat-y;}
1371
.another-thing { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) 0 -767px repeat-x; }
1372
#whatevz {background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) center top no-repeat;}
1373
1374
.widget ul li { background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=) top center; }
1375
CSS;
1376
1377
        // For test purposes, ALL images in the css are being inlined with a 1x1 trans png string/datauri.
1378
        add_filter( 'autoptimize_filter_css_is_datauri_candidate', function( $is_candidate, $path ) {
0 ignored issues
show
Unused Code introduced by
The parameter $is_candidate is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1379
            return true;
1380
        }, 10, 2 );
1381
1382
        // For test purposes, ALL images in the css are being inlined with a 1x1 trans png string/datauri.
1383 View Code Duplication
        add_filter( 'autoptimize_filter_css_datauri_image', function( $base64array, $path ) {
0 ignored issues
show
Unused Code introduced by
The parameter $base64array is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1384
            $head = 'data:image/png;base64,';
1385
            $data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
1386
1387
            $result['full']       = $head . $data;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1388
            $result['base64data'] = $data;
1389
            return $result;
1390
        }, 10, 2 );
1391
1392
        $instance = new autoptimizeStyles( $css_orig );
1393
        $instance->setOption( 'datauris', true );
1394
        $css_actual = $instance->rewrite_assets( $css_orig );
1395
        $this->assertEquals( $css_expected, $css_actual );
1396
    }
1397
1398
    /**
1399
     * Test css with fonts pointed to the CDN + cdn_url option is set.
1400
     */
1401
    public function test_css_fonts_on_cdn_with_filter()
1402
    {
1403
        $urls    = $this->get_urls();
1404
        $siteurl = $urls['siteurl'];
1405
        $cdnurl  = $urls['cdnurl'];
1406
        $sub     = $urls['subfolder'];
1407
1408
        $css_in = <<<CSS
1409
/* these should not be touched except for quotes removal */
1410
@font-face {
1411
  font-family: 'Roboto';
1412
  font-style: normal;
1413
  font-weight: 100;
1414
  src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1415
  src: local('Roboto Thin'), local('Roboto-Thin'),
1416
       url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1417
       url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1418
       url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1419
       url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1420
       url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1421
}
1422
@font-face {
1423
  font-family: 'Roboto';
1424
  font-style: normal;
1425
  font-weight: 100;
1426
  src: url('//fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1427
  src: local('Roboto Thin'), local('Roboto-Thin'),
1428
       url('//fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1429
       url('//fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1430
       url('//fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1431
       url('//fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1432
       url('//fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1433
}
1434
/* these will be replaced and quotes gone */
1435
@font-face {
1436
  font-family: 'Roboto';
1437
  font-style: normal;
1438
  font-weight: 100;
1439
  src: url('/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1440
  src: local('Roboto Thin'), local('Roboto-Thin'),
1441
       url('/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1442
       url('/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1443
       url('/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1444
       url('/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1445
       url('/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1446
}
1447
@font-face {
1448
  font-family: 'Roboto';
1449
  font-style: normal;
1450
  font-weight: 100;
1451
  src: url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1452
  src: local('Roboto Thin'), local('Roboto-Thin'),
1453
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1454
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1455
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1456
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1457
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1458
}
1459
CSS;
1460
1461
        $css_expected_fonts_cdn = <<<CSS
1462
/* these should not be touched except for quotes removal */
1463
@font-face {
1464
  font-family: 'Roboto';
1465
  font-style: normal;
1466
  font-weight: 100;
1467
  src: url(../fonts/roboto-v15-latin-ext_latin-100.eot); /* IE9 Compat Modes */
1468
  src: local('Roboto Thin'), local('Roboto-Thin'),
1469
       url(../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'), /* IE6-IE8 */
1470
       url(../fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'), /* Super Modern Browsers */
1471
       url(../fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'), /* Modern Browsers */
1472
       url(../fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'), /* Safari, Android, iOS */
1473
       url(../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg'); /* Legacy iOS */
1474
}
1475
@font-face {
1476
  font-family: 'Roboto';
1477
  font-style: normal;
1478
  font-weight: 100;
1479
  src: url(//fonts/roboto-v15-latin-ext_latin-100.eot); /* IE9 Compat Modes */
1480
  src: local('Roboto Thin'), local('Roboto-Thin'),
1481
       url(//fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'), /* IE6-IE8 */
1482
       url(//fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'), /* Super Modern Browsers */
1483
       url(//fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'), /* Modern Browsers */
1484
       url(//fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'), /* Safari, Android, iOS */
1485
       url(//fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg'); /* Legacy iOS */
1486
}
1487
/* these will be replaced and quotes gone */
1488
@font-face {
1489
  font-family: 'Roboto';
1490
  font-style: normal;
1491
  font-weight: 100;
1492
  src: url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.eot); /* IE9 Compat Modes */
1493
  src: local('Roboto Thin'), local('Roboto-Thin'),
1494
       url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'), /* IE6-IE8 */
1495
       url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'), /* Super Modern Browsers */
1496
       url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'), /* Modern Browsers */
1497
       url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'), /* Safari, Android, iOS */
1498
       url(${cdnurl}/${sub}fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg'); /* Legacy iOS */
1499
}
1500
@font-face {
1501
  font-family: 'Roboto';
1502
  font-style: normal;
1503
  font-weight: 100;
1504
  src: url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot); /* IE9 Compat Modes */
1505
  src: local('Roboto Thin'), local('Roboto-Thin'),
1506
       url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix) format('embedded-opentype'), /* IE6-IE8 */
1507
       url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff2) format('woff2'), /* Super Modern Browsers */
1508
       url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff) format('woff'), /* Modern Browsers */
1509
       url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.ttf) format('truetype'), /* Safari, Android, iOS */
1510
       url(${cdnurl}/${sub}wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto) format('svg'); /* Legacy iOS */
1511
}
1512
CSS;
1513
1514
        // Test with fonts pointed to the CDN + cdn option is set.
1515
        add_filter( 'autoptimize_filter_css_fonts_cdn', '__return_true' );
1516
        $instance = new autoptimizeStyles( $css_in );
1517
        $instance->setOption( 'cdn_url', $cdnurl );
1518
        $css_actual_fonts_cdn = $instance->rewrite_assets( $css_in );
1519
1520
        $this->assertEquals( $css_expected_fonts_cdn, $css_actual_fonts_cdn );
1521
    }
1522
1523
    /**
1524
     * Test css fonts not moved to cdn by default even if cdn_url option is set.
1525
     */
1526
    public function test_css_fonts_skipped_by_default_even_when_cdn_is_set()
1527
    {
1528
        $urls      = $this->get_urls();
1529
        $siteurl   = $urls['siteurl'];
1530
        $subfolder = $urls['subfolder'];
0 ignored issues
show
Unused Code introduced by
$subfolder is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1531
1532
        $css_in = <<<CSS
1533
/* these should not be changed, not even quotes */
1534
@font-face {
1535
  font-family: 'Roboto';
1536
  font-style: normal;
1537
  font-weight: 100;
1538
  src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1539
  src: local('Roboto Thin'), local('Roboto-Thin'),
1540
       url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1541
       url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1542
       url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1543
       url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1544
       url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1545
}
1546
@font-face {
1547
  font-family: 'Roboto';
1548
  font-style: normal;
1549
  font-weight: 100;
1550
  src: url('//fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1551
  src: local('Roboto Thin'), local('Roboto-Thin'),
1552
       url('//fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1553
       url('//fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1554
       url('//fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1555
       url('//fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1556
       url('//fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1557
}
1558
@font-face {
1559
  font-family: 'Roboto';
1560
  font-style: normal;
1561
  font-weight: 100;
1562
  src: url('/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1563
  src: local('Roboto Thin'), local('Roboto-Thin'),
1564
       url('/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1565
       url('/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1566
       url('/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1567
       url('/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1568
       url('/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1569
}
1570
@font-face {
1571
  font-family: 'Roboto';
1572
  font-style: normal;
1573
  font-weight: 100;
1574
  src: url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1575
  src: local('Roboto Thin'), local('Roboto-Thin'),
1576
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1577
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1578
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1579
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1580
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1581
}
1582
CSS;
1583
        // Expected without cdning fonts but cdn option is set.
1584
        $css_expected = <<<CSS
1585
/* these should not be changed, not even quotes */
1586
@font-face {
1587
  font-family: 'Roboto';
1588
  font-style: normal;
1589
  font-weight: 100;
1590
  src: url('../fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1591
  src: local('Roboto Thin'), local('Roboto-Thin'),
1592
       url('../fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1593
       url('../fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1594
       url('../fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1595
       url('../fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1596
       url('../fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1597
}
1598
@font-face {
1599
  font-family: 'Roboto';
1600
  font-style: normal;
1601
  font-weight: 100;
1602
  src: url('//fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1603
  src: local('Roboto Thin'), local('Roboto-Thin'),
1604
       url('//fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1605
       url('//fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1606
       url('//fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1607
       url('//fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1608
       url('//fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1609
}
1610
@font-face {
1611
  font-family: 'Roboto';
1612
  font-style: normal;
1613
  font-weight: 100;
1614
  src: url('/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1615
  src: local('Roboto Thin'), local('Roboto-Thin'),
1616
       url('/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1617
       url('/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1618
       url('/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1619
       url('/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1620
       url('/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1621
}
1622
@font-face {
1623
  font-family: 'Roboto';
1624
  font-style: normal;
1625
  font-weight: 100;
1626
  src: url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot'); /* IE9 Compat Modes */
1627
  src: local('Roboto Thin'), local('Roboto-Thin'),
1628
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
1629
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff2') format('woff2'), /* Super Modern Browsers */
1630
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.woff') format('woff'), /* Modern Browsers */
1631
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.ttf') format('truetype'), /* Safari, Android, iOS */
1632
       url('$siteurl/wp-content/themes/mytheme/fonts/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg'); /* Legacy iOS */
1633
}
1634
CSS;
1635
        // Test without moving fonts to CDN, but cdn option is set.
1636
        $instance = new autoptimizeStyles( $css_in );
1637
        $instance->setOption( 'cdn_url', $urls['cdnurl'] );
1638
        $css_actual = $instance->rewrite_assets( $css_in );
1639
        $this->assertEquals( $css_expected, $css_actual );
1640
    }
1641
1642
    public function test_assets_regex_replaces_multi_bg_images()
1643
    {
1644
        $urls   = $this->get_urls();
1645
        $sub    = $urls['subfolder'];
1646
        $cdnurl = $urls['cdnurl'];
1647
1648
        $in = <<<CSS
1649
body:after {
1650
  content: url(/img/close.png) url(/img/loading.gif) url(/img/prev.png) url(/img/next.png);
1651
}
1652
CSS;
1653
1654
        $expected = <<<CSS
1655
body:after {
1656
  content: url($cdnurl/${sub}img/close.png) url($cdnurl/${sub}img/loading.gif) url($cdnurl/${sub}img/prev.png) url($cdnurl/${sub}img/next.png);
1657
}
1658
CSS;
1659
1660
        $instance = new autoptimizeStyles( $in );
1661
        $instance->setOption( 'cdn_url', $cdnurl );
1662
        $actual = $instance->rewrite_assets( $in );
1663
1664
        $this->assertEquals( $expected, $actual );
1665
    }
1666
1667
    public function test_at_supports_spacing_issue_110()
1668
    {
1669
        $in       = <<<CSS
1670
@supports (-webkit-filter: blur(3px)) or (filter: blur(3px)) {
1671
    .blur {
1672
        filter:blur(3px);
1673
    }
1674
}
1675
@supports((position:-webkit-sticky) or (position:sticky)) {
1676
    .sticky { position:sticky; }
1677
}
1678
CSS;
1679
        $expected = <<<CSS
1680
@supports (-webkit-filter:blur(3px)) or (filter:blur(3px)){.blur{filter:blur(3px)}}@supports((position:-webkit-sticky) or (position:sticky)){.sticky{position:sticky}}
1681
CSS;
1682
1683
        $instance = new autoptimizeStyles( $in );
1684
        $actual   = $instance->run_minifier_on( $in );
1685
1686
        $this->assertEquals( $expected, $actual );
1687
    }
1688
1689 View Code Duplication
    public function test_css_import_semicolon_url_issue_122()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1690
    {
1691
        $urls   = $this->get_urls();
1692
        $sub    = $urls['subfolder'];
1693
        $cdnurl = $urls['cdnurl'];
1694
1695
        $in = <<<HTML
1696
<style type="text/css">
1697
@import url("foo.css?a&#038;b");
1698
@import url("bar.css");
1699
</style>
1700
HTML;
1701
1702
        $expected = '<style media="all">@import url(' . $cdnurl . '/' . $sub . 'foo.css?a&#038;b);@import url(' . $cdnurl . '/' . $sub . 'bar.css);</style><!--noptimize--><!-- Autoptimize found a problem with the HTML in your Theme, tag `title` missing --><!--/noptimize-->';
1703
1704
        $options = [
1705
            'autoptimizeStyles' => $this->getAoStylesDefaultOptions(),
1706
        ];
1707
1708
        $instance = new autoptimizeStyles( $in );
1709
        $instance->read( $options['autoptimizeStyles'] );
1710
        $instance->minify();
1711
        $instance->cache();
1712
        $actual = $instance->getcontent();
1713
        $this->assertEquals( $expected, $actual );
1714
    }
1715
1716
    public function test_fixurls_with_at_imports_and_media_queries()
1717
    {
1718
        $urls      = $this->get_urls();
1719
        $prsiteurl = $urls['prsiteurl'];
1720
        $subfolder = $urls['subfolder'];
0 ignored issues
show
Unused Code introduced by
$subfolder is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1721
1722
        $in  = '@import "foo.css"; @import "bar.css" (orientation:landscape);';
1723
        $exp = '@import url(' . $prsiteurl . '/wp-content/themes/my-theme/foo.css); @import url(' . $prsiteurl . '/wp-content/themes/my-theme/bar.css) (orientation:landscape);';
1724
1725
        $actual = autoptimizeStyles::fixurls( ABSPATH . 'wp-content/themes/my-theme/style.css', $in );
1726
        $this->assertEquals( $exp, $actual );
1727
    }
1728
1729 View Code Duplication
    public function test_aostyles_at_imports_with_media_queries()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1730
    {
1731
        $urls   = $this->get_urls();
1732
        $sub    = $urls['subfolder'];
1733
        $cdnurl = $urls['cdnurl'];
1734
1735
        $in = <<<HTML
1736
<style type="text/css">
1737
@import "foo.css"; @import "bar.css" (orientation:landscape);
1738
</style>
1739
HTML;
1740
1741
        $expected = '<style media="all">@import url(' . $cdnurl . '/' . $sub . 'foo.css);@import url(' . $cdnurl . '/' . $sub . 'bar.css) (orientation:landscape);</style><!--noptimize--><!-- Autoptimize found a problem with the HTML in your Theme, tag `title` missing --><!--/noptimize-->';
1742
1743
        $options = [
1744
            'autoptimizeStyles' => $this->getAoStylesDefaultOptions(),
1745
        ];
1746
1747
        $instance = new autoptimizeStyles( $in );
1748
        $instance->read( $options['autoptimizeStyles'] );
1749
        $instance->minify();
1750
        $instance->cache();
1751
1752
        $actual = $instance->getcontent();
1753
        $this->assertEquals( $expected, $actual );
1754
    }
1755
1756
    public function test_cache_size_checker_hooked_by_default()
1757
    {
1758
        $this->assertNotEmpty( autoptimizeCacheChecker::SCHEDULE_HOOK );
1759
1760
        // No schedule, because it's only added when is_admin() is true.
1761
        $this->assertEquals( false, wp_get_schedule( autoptimizeCacheChecker::SCHEDULE_HOOK ) );
1762
1763
        // Proving that setup() sets the schedule as needed.
1764
        $checker = new autoptimizeCacheChecker();
1765
        $checker->setup();
1766
        $this->assertEquals( 'twicedaily', wp_get_schedule( autoptimizeCacheChecker::SCHEDULE_HOOK ) );
1767
    }
1768
1769
    public function test_cache_size_checker_disabled_with_filter()
1770
    {
1771
        add_filter( 'autoptimize_filter_cachecheck_do', '__return_false' );
1772
1773
        $checker = new autoptimizeCacheChecker();
1774
        $checker->setup();
1775
        $this->assertEquals( false, wp_get_schedule( autoptimizeCacheChecker::SCHEDULE_HOOK ) );
1776
1777
        remove_all_filters( 'autoptimize_filter_cachecheck_do' );
1778
    }
1779
1780
    public function test_is_start_buffering_hooked_properly()
1781
    {
1782
        $instance = autoptimize();
1783
1784
        /**
1785
         * TODO/FIXME: ideally, we'd test all possible setups, but once we set
1786
         * a constant, there's no going back, unless we use runkit or somesuch:
1787
         * https://www.theaveragedev.com/mocking-constants-in-tests/.
1788
         */
1789
1790
        if ( defined( 'AUTOPTIMIZE_INIT_EARLIER' ) ) {
1791
            $this->assertEquals(
1792
                autoptimizeMain::INIT_EARLIER_PRIORITY,
1793
                has_action( 'init', array( $instance, 'start_buffering' ) )
1794
            );
1795
            $this->assertTrue( ! defined( 'AUTOPTIMIZE_HOOK_INTO' ) );
1796
        }
1797
1798
        /*
1799
        // AUTOPTIMIZE_HOOK_INTO only exists if AUTOPTIMIZE_INIT_EARLIER doesnt
1800
        $this->assertEquals(
1801
            autoptimizeMain::DEFAULT_HOOK_PRIORITY,
1802
            has_action( constant( 'AUTOPTIMIZE_HOOK_INTO' ), array( $instance, 'start_buffering' ) )
1803
        );
1804
        $this->assertFalse(
1805
            has_action( 'init', array( $instance, 'start_buffering' ) )
1806
        );
1807
        */
1808
    }
1809
1810
    public function test_inline_and_defer_markup()
1811
    {
1812
        add_filter( 'autoptimize_filter_css_defer', '__return_true' );
1813
        add_filter( 'autoptimize_filter_css_defer_inline', '__return_true' );
1814
1815
        $actual = $this->ao->end_buffering( $this->get_test_markup() );
1816
        if ( is_multisite() ) {
1817
            $this->assertEquals( $this->get_test_markup_output_inline_defer_ms(), $actual );
1818
        } else {
1819
            $this->assertEquals( $this->get_test_markup_output_inline_defer(), $actual );
1820
        }
1821
1822
        remove_all_filters( 'autoptimize_filter_css_defer' );
1823
        remove_all_filters( 'autoptimize_filter_css_defer_inline' );
1824
    }
1825
1826 View Code Duplication
    public function test_js_aggregation_decision_and_dontaggregate_filter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1827
    {
1828
        $opts = $this->getAoScriptsDefaultOptions();
1829
1830
        // Aggregating: true by default.
1831
        $scripts = new autoptimizeScripts( '' );
1832
        $scripts->read( $opts );
1833
        $this->assertTrue( $scripts->aggregating() );
1834
1835
        // Aggregating: option=true (dontaggregate=false by default).
1836
        $opts['aggregate'] = true;
1837
        $scripts           = new autoptimizeScripts( '' );
1838
        $scripts->read( $opts );
1839
        $this->assertTrue( $scripts->aggregating() );
1840
1841
        // Aggregating: option=true, dontaggregate=false explicit.
1842
        $opts['aggregate'] = true;
1843
        add_filter( 'autoptimize_filter_js_dontaggregate', '__return_false' );
1844
        $scripts = new autoptimizeScripts( '' );
1845
        $scripts->read( $opts );
1846
        $this->assertTrue( $scripts->aggregating() );
1847
        remove_all_filters( 'autoptimize_filter_js_dontaggregate' );
1848
1849
        // Not aggregating: option=true, dontaggregate=true.
1850
        $opts['aggregate'] = true;
1851
        add_filter( 'autoptimize_filter_js_dontaggregate', '__return_true' );
1852
        $scripts = new autoptimizeScripts( '' );
1853
        $scripts->read( $opts );
1854
        $this->assertFalse( $scripts->aggregating() );
1855
        remove_all_filters( 'autoptimize_filter_js_dontaggregate' );
1856
1857
        // Not aggregating: option=false, dontaggregate=false.
1858
        $opts['aggregate'] = false;
1859
        add_filter( 'autoptimize_filter_js_dontaggregate', '__return_false' );
1860
        $scripts = new autoptimizeScripts( '' );
1861
        $scripts->read( $opts );
1862
        $this->assertFalse( $scripts->aggregating() );
1863
        remove_all_filters( 'autoptimize_filter_js_dontaggregate' );
1864
1865
        // Not aggregating: option=false, dontaggregate=true.
1866
        $opts['aggregate'] = false;
1867
        add_filter( 'autoptimize_filter_js_dontaggregate', '__return_true' );
1868
        $scripts = new autoptimizeScripts( '' );
1869
        $scripts->read( $opts );
1870
        $this->assertFalse( $scripts->aggregating() );
1871
        remove_all_filters( 'autoptimize_filter_js_dontaggregate' );
1872
    }
1873
1874 View Code Duplication
    public function test_css_aggregation_decision_and_dontaggregate_filter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1875
    {
1876
        $opts = $this->getAoStylesDefaultOptions();
1877
1878
        // Aggregating: true by default.
1879
        $styles = new autoptimizeStyles( '' );
1880
        $this->assertTrue( $styles->aggregating() );
1881
1882
        // Aggregating: option=true (dontaggregate=false by default).
1883
        $opts['aggregate'] = true;
1884
        $styles            = new autoptimizeStyles( '' );
1885
        $styles->read( $opts );
1886
        $this->assertTrue( $styles->aggregating() );
1887
1888
        // Aggregating: option=true, dontaggregate=false explicit.
1889
        $opts['aggregate'] = true;
1890
        add_filter( 'autoptimize_filter_css_dontaggregate', '__return_false' );
1891
        $styles = new autoptimizeStyles( '' );
1892
        $styles->read( $opts );
1893
        $this->assertTrue( $styles->aggregating() );
1894
        remove_all_filters( 'autoptimize_filter_css_dontaggregate' );
1895
1896
        // Not aggregating: option=true, dontaggregate=true.
1897
        $opts['aggregate'] = true;
1898
        add_filter( 'autoptimize_filter_css_dontaggregate', '__return_true' );
1899
        $styles = new autoptimizeStyles( '' );
1900
        $styles->read( $opts );
1901
        $this->assertFalse( $styles->aggregating() );
1902
        remove_all_filters( 'autoptimize_filter_css_dontaggregate' );
1903
1904
        // Not aggregating: option=false, dontaggregate=false.
1905
        $opts['aggregate'] = false;
1906
        add_filter( 'autoptimize_filter_css_dontaggregate', '__return_false' );
1907
        $styles = new autoptimizeStyles( '' );
1908
        $styles->read( $opts );
1909
        $this->assertFalse( $styles->aggregating() );
1910
        remove_all_filters( 'autoptimize_filter_css_dontaggregate' );
1911
1912
        // Not aggregating: option=false, dontaggregate=true.
1913
        $opts['aggregate'] = false;
1914
        add_filter( 'autoptimize_filter_css_dontaggregate', '__return_true' );
1915
        $styles = new autoptimizeStyles( '' );
1916
        $styles->read( $opts );
1917
        $this->assertFalse( $styles->aggregating() );
1918
        remove_all_filters( 'autoptimize_filter_css_dontaggregate' );
1919
    }
1920
1921
    public function test_css_minify_single_with_cdning()
1922
    {
1923
        $pathname = dirname( __FILE__ ) . '/fixtures/minify-single.css';
1924
        $opts     = $this->getAoStylesDefaultOptions();
1925
        $styles   = new autoptimizeStyles( '' );
1926
        $styles->read( $opts );
1927
1928
        $url = $styles->minify_single( $pathname, $cache_miss = true );
1929
1930
        // Minified url filename + its pointed to cdn.
1931
        $this->assertContains( AUTOPTIMIZE_CACHE_CHILD_DIR, $url );
1932
        $this->assertContains( '/autoptimize_single_', $url );
1933
        $this->assertContains( $styles->cdn_url, $url );
1934
1935
        // Actual minified css contents are minified and cdn-ed.
1936
        $path     = $styles->getpath( $url );
0 ignored issues
show
Security Bug introduced by
It seems like $url defined by $styles->minify_single($...me, $cache_miss = true) on line 1928 can also be of type false; however, autoptimizeBase::getpath() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1937
        $contents = file_get_contents( $path );
1938
        $this->assertContains( $styles->cdn_url, $contents );
1939
        $this->assertContains( '.bg{background:url(' . $styles->cdn_url, $contents );
1940
    }
1941
1942
    public function test_ao_partners_instantiation_without_explicit_include()
1943
    {
1944
        $partners = new autoptimizePartners();
1945
        $this->assertTrue( $partners instanceof autoptimizePartners );
1946
    }
1947
1948 View Code Duplication
    public function test_html_minify_keep_html_comments_inside_script_blocks()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1949
    {
1950
        $markup   = <<<MARKUP
1951
<script>
1952
<!-- End Support AJAX add to cart -->
1953
var a = "b";
1954
</script>
1955
MARKUP;
1956
        $expected = <<<MARKUP
1957
<script><!-- End Support AJAX add to cart -->
1958
var a = "b";</script>
1959
MARKUP;
1960
1961
        $markup2 = <<<MARKUP
1962
<script>
1963
var a = "b";
1964
<!-- End Support AJAX add to cart -->
1965
</script>
1966
MARKUP;
1967
1968
        $expected2 = <<<MARKUP
1969
<script>var a = "b";
1970
<!-- End Support AJAX add to cart --></script>
1971
MARKUP;
1972
1973
        // When keepcomments is true.
1974
        $options = [
1975
            'autoptimizeHTML' => [
1976
                'keepcomments' => true,
1977
            ],
1978
        ];
1979
1980
        $instance = new autoptimizeHTML( $markup );
1981
        $instance->read( $options['autoptimizeHTML'] );
1982
        $instance->minify();
1983
        $actual = $instance->getcontent();
1984
        $this->assertEquals( $expected, $actual );
1985
1986
        $instance = new autoptimizeHTML( $markup2 );
1987
        $instance->read( $options['autoptimizeHTML'] );
1988
        $instance->minify();
1989
        $actual2 = $instance->getcontent();
1990
        $this->assertEquals( $expected2, $actual2 );
1991
    }
1992
1993 View Code Duplication
    public function test_html_minify_remove_html_comments_inside_script_blocks()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1994
    {
1995
        // Default case, html comments removed (keepcomments = false).
1996
        $markup1   = <<<MARKUP
1997
<script>
1998
var a = "b";
1999
<!-- End Support AJAX add to cart -->
2000
</script>
2001
MARKUP;
2002
        $expected1 = <<<MARKUP
2003
<script>var a = "b";
2004
<!-- End Support AJAX add to cart</script>
2005
MARKUP;
2006
2007
        $markup2   = <<<MARKUP
2008
<script>
2009
<!-- End Support AJAX add to cart -->
2010
var a = "b";
2011
</script>
2012
MARKUP;
2013
        $expected2 = <<<MARKUP
2014
<script>End Support AJAX add to cart -->
2015
var a = "b";</script>
2016
MARKUP;
2017
2018
        $options = [
2019
            'autoptimizeHTML' => [
2020
                'keepcomments' => false,
2021
            ],
2022
        ];
2023
2024
        $instance = new autoptimizeHTML( $markup1 );
2025
        $instance->read( $options['autoptimizeHTML'] );
2026
        $instance->minify();
2027
        $actual = $instance->getcontent();
2028
        $this->assertEquals( $expected1, $actual );
2029
2030
        $instance = new autoptimizeHTML( $markup2 );
2031
        $instance->read( $options['autoptimizeHTML'] );
2032
        $instance->minify();
2033
        $actual2 = $instance->getcontent();
2034
        $this->assertEquals( $expected2, $actual2 );
2035
    }
2036
2037 View Code Duplication
    public function test_html_minify_html_comments_inside_script_blocks_old_school_pattern()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2038
    {
2039
        $markup = <<<MARKUP
2040
<script>
2041
<!-- // invisible for old browsers
2042
var a = "z";
2043
// -->
2044
</script>
2045
MARKUP;
2046
2047
        $expected = <<<MARKUP
2048
<script>// invisible for old browsers
2049
var a = "z";</script>
2050
MARKUP;
2051
2052
        $options = [
2053
            'autoptimizeHTML' => [
2054
                'keepcomments' => false,
2055
            ],
2056
        ];
2057
2058
        $instance = new autoptimizeHTML( $markup );
2059
        $instance->read( $options['autoptimizeHTML'] );
2060
        $instance->minify();
2061
        $actual = $instance->getcontent();
2062
        $this->assertEquals( $expected, $actual );
2063
    }
2064
2065 View Code Duplication
    public function test_html_minify_html_comments_inside_script_blocks_old_school_pattern_untouched()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2066
    {
2067
        $markup = <<<MARKUP
2068
<script>
2069
<!-- // invisible for old browsers
2070
var a = "z";
2071
// -->
2072
</script>
2073
MARKUP;
2074
2075
        $expected = <<<MARKUP
2076
<script><!-- // invisible for old browsers
2077
var a = "z";
2078
// --></script>
2079
MARKUP;
2080
2081
        $options = [
2082
            'autoptimizeHTML' => [
2083
                'keepcomments' => true,
2084
            ],
2085
        ];
2086
2087
        $instance = new autoptimizeHTML( $markup );
2088
        $instance->read( $options['autoptimizeHTML'] );
2089
        $instance->minify();
2090
        $actual = $instance->getcontent();
2091
        $this->assertEquals( $expected, $actual );
2092
    }
2093
2094
    public function test_utils_mbstring_availabilty_overriding()
2095
    {
2096
        $orig     = autoptimizeUtils::mbstring_available();
2097
        $opposite = ! $orig;
2098
2099
        $this->assertSame( $orig, autoptimizeUtils::mbstring_available() );
2100
        // Override works...
2101
        $this->assertSame( $opposite, autoptimizeUtils::mbstring_available( $opposite ) );
2102
        // And override remains cached as the last version.
2103
        $this->assertSame( $opposite, autoptimizeUtils::mbstring_available() );
2104
    }
2105
2106
    public function test_utils_mbstring_basics()
2107
    {
2108
        // Turn on mbstring usage.
2109
        autoptimizeUtils::mbstring_available( true );
2110
2111
        $this->assertSame( 2, autoptimizeUtils::strlen( "\x00\xFF", 'ASCII' ) );
2112
        $this->assertSame( 2, autoptimizeUtils::strlen( "\x00\xFF", 'CP850' ) );
2113
        $this->assertSame( 3, autoptimizeUtils::strlen( '한국어' ) );
2114
2115
        $this->assertFalse( @autoptimizeUtils::strpos( 'abc', '' ) );
2116
        $this->assertFalse( @autoptimizeUtils::strpos( 'abc', 'a', -1 ) );
2117
        $this->assertFalse( autoptimizeUtils::strpos( 'abc', 'd' ) );
2118
        $this->assertFalse( autoptimizeUtils::strpos( 'abc', 'a', 3 ) );
2119
        $this->assertSame( 1, autoptimizeUtils::strpos( '한국어', '국' ) );
2120
    }
2121
2122
    /**
2123
     * @dataProvider provider_utils_substr_replace
2124
     */
2125
    function test_utils_substr_replace_basics_mbstring( $s, $repl, $start, $len, $expected )
2126
    {
2127
        // Force mbstring code path...
2128
        autoptimizeUtils::mbstring_available( true );
2129
        $this->assertEquals( $expected, autoptimizeUtils::substr_replace( $s, $repl, $start, $len ) );
2130
    }
2131
2132
    public function provider_utils_substr_replace()
2133
    {
2134
        $str  = 'try this';
2135
        $repl = 'bala ';
2136
2137
        return [
2138
            [
2139
                $str,
2140
                $repl,
2141
                2,
2142
                null,
2143
                'trbala ',
2144
            ],
2145
            [
2146
                $str,
2147
                $repl,
2148
                2,
2149
                3,
2150
                'trbala his',
2151
            ],
2152
            [
2153
                $str,
2154
                $repl,
2155
                2,
2156
                0,
2157
                'trbala y this',
2158
            ],
2159
            [
2160
                $str,
2161
                $repl,
2162
                2,
2163
                -2,
2164
                'trbala is',
2165
            ],
2166
        ];
2167
    }
2168
2169 View Code Duplication
    function test_mb_substr_replace_with_ascii_input_string()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2170
    {
2171
        autoptimizeUtils::mbstring_available( false );
2172
2173
        $str = 'Ascii';
2174
2175
        $this->assertSame( 'Añ', autoptimizeUtils::substr_replace( $str, 'ñ', 1 ) );
2176
        $this->assertSame( 'ñcii', autoptimizeUtils::substr_replace( $str, 'ñ', 0, 2 ) );
2177
        $this->assertSame( 'Asñx', autoptimizeUtils::substr_replace( $str, 'ñx', 2, 3 ) );
2178
        $this->assertSame( 'Asz', autoptimizeUtils::substr_replace( $str, 'z', 2, 10 ) );
2179
        $this->assertSame( 'Añii', autoptimizeUtils::substr_replace( $str, 'ñ', 1, 2 ) );
2180
    }
2181
2182 View Code Duplication
    function test_mb_substr_replace_with_utf8_input_string()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2183
    {
2184
        autoptimizeUtils::mbstring_available( true );
2185
2186
        $str = 'âønæë';
2187
2188
        $this->assertSame( 'âñ', autoptimizeUtils::substr_replace( $str, 'ñ', 1 ) ); // No length.
2189
        $this->assertSame( 'ñnæë', autoptimizeUtils::substr_replace( $str, 'ñ', 0, 2 ) );
2190
        $this->assertSame( 'âøñx', autoptimizeUtils::substr_replace( $str, 'ñx', 2, 3 ) );
2191
        $this->assertSame( 'âøz', autoptimizeUtils::substr_replace( $str, 'z', 2, 10 ) ); // Length larger than possible...
2192
        $this->assertSame( 'âñæë', autoptimizeUtils::substr_replace( $str, 'ñ', 1, 2 ) );
2193
    }
2194
2195 View Code Duplication
    function test_default_substr_replace_with_ascii_input_string()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2196
    {
2197
        // Disable mbstring which should fall ack to substr_replace...
2198
        autoptimizeUtils::mbstring_available( false );
2199
2200
        $str = 'Ascii';
2201
2202
        $this->assertSame( 'Añ', autoptimizeUtils::substr_replace( $str, 'ñ', 1 ) );
2203
        $this->assertSame( 'ñcii', autoptimizeUtils::substr_replace( $str, 'ñ', 0, 2 ) );
2204
        $this->assertSame( 'Asñx', autoptimizeUtils::substr_replace( $str, 'ñx', 2, 3 ) );
2205
        $this->assertSame( 'Asz', autoptimizeUtils::substr_replace( $str, 'z', 2, 10 ) );
2206
        $this->assertSame( 'Añii', autoptimizeUtils::substr_replace( $str, 'ñ', 1, 2 ) );
2207
    }
2208
2209
    function test_default_substr_replace_with_utf8_input_string()
2210
    {
2211
        // Disabling mbstring, falling back to substr_replace...
2212
        autoptimizeUtils::mbstring_available( false );
2213
2214
        // This is really impossible to make work properly, since
2215
        // any start/len parameters we give are working with bytes instead
2216
        // of characters, shit just breaks.
2217
        $str = 'âønæë';
2218
2219
        // $this->assertSame( '�ñ', autoptimizeUtils::substr_replace( $str, 'ñ', 1 ) ); // No length.
2220
        // $this->assertSame( 'ñ�næë', autoptimizeUtils::substr_replace( $str, 'ñ', 1, 2 ) );
2221
        $this->assertSame( 'ñønæë', autoptimizeUtils::substr_replace( $str, 'ñ', 0, 2 ) );
2222
        $this->assertSame( 'âñxæë', autoptimizeUtils::substr_replace( $str, 'ñx', 2, 3 ) );
2223
        $this->assertSame( 'âz', autoptimizeUtils::substr_replace( $str, 'z', 2, 10 ) ); // Length larger than possible...
2224
    }
2225
2226
    public function test_cache_fast_delete()
2227
    {
2228
        add_filter( 'autoptimize_filter_cache_clear_advanced', '__return_true' );
2229
2230
        autoptimizeCache::clearall_actionless();
2231
2232
        remove_all_filters( 'autoptimize_filter_cache_clear_advanced' );
2233
    }
2234
2235
    public function test_delete_advanced_cache_clear_artifacts()
2236
    {
2237
        add_filter( 'autoptimize_filter_cache_clear_advanced', '__return_true' );
2238
2239
        $this->assertTrue( autoptimizeCache::delete_advanced_cache_clear_artifacts() );
2240
2241
        remove_all_filters( 'autoptimize_filter_cache_clear_advanced' );
2242
    }
2243
2244
    public function provider_canonicalization()
2245
    {
2246
        return array(
2247
            array( '../common', 'common' ),
2248
            array( '../what-does-this-mean/really?/', 'what-does-this-mean/really?/' ),
2249
            array( '../../what/where/how', 'what/where/how' ),
2250
            array( '/../more.dots.please/', '/more.dots.please/' ),
2251
            array( '/../../what/where/how', '/what/where/how' ),
2252
            array( '/a/b/c/../../../d/e/file.txt', '/d/e/file.txt' ),
2253
            array( 'a/b/../c', 'a/c' ),
2254
            array( './../../etc/passwd', './etc/passwd' ),
2255
            array( '/var/.////./user/./././..//.//../////../././.././test/////', '/test/' ),
2256
            array( '/var/user/./././.././../.././././test/', '/test/' ),
2257
            array( '/hello/0//how/../are/../you', '/hello/0/you' ),
2258
            array( '', '' ),
2259
            array( '.', '.' ),
2260
            array( '..', '..' ),
2261
            array( './..', './..' ),
2262
            array( '../.', '.' ),
2263
            // This might be debatable...
2264
            array( '../..', '..' ),
2265
        );
2266
    }
2267
2268
    /**
2269
     * @dataProvider provider_canonicalization
2270
     */
2271
    public function test_path_canonicalize( $path, $canonicalized )
2272
    {
2273
        $this->assertSame( $canonicalized, autoptimizeUtils::path_canonicalize( $path ) );
2274
    }
2275
2276
    /**
2277
     * For a site in subfolder, CDN-rewrite used to magically include
2278
     * the subfolder when rewriting assets to CDN.
2279
     * That behavior can be turned off by returning false via
2280
     * `autoptimize_filter_cdn_magic_path_check`.
2281
     * If it's false, cdn-rewriting should not include subfolder even
2282
     * when the site is actually in a subfolder/subdirectory.
2283
     */
2284
    public function test_autoptimize_filter_cdn_magic_path_check()
2285
    {
2286
        $cdnurl = 'http://cdn.example.org';
2287
        add_filter( 'autoptimize_filter_cdn_magic_path_check', '__return_false', 10, 2 );
2288
2289
        // Even when site is in a subfolder, the resulting cdn-rewritten url
2290
        // should not magically include it, due to the above filter.
2291
        // The second parameter is here to force a cache miss and re-run
2292
        // the filter since we're using the same cdn url all over the place,
2293
        // but want to prove different things with it.
2294
        $this->assertSame( $cdnurl, autoptimizeUtils::tweak_cdn_url_if_needed( $cdnurl, true ) );
2295
2296
        remove_all_filters( 'autoptimize_filter_cdn_magic_path_check' );
2297
    }
2298
2299
    /**
2300
     * Test image optimization in autoptimizeImages.php.
2301
     *
2302
     * Default case: img with srcsets
2303
     */
2304
    public function test_imgopt()
2305
    {
2306
        $urls                                        = $this->get_urls();
2307
        $siteurl                                     = $urls['siteurl'];
2308
        $imgopthost                                  = $urls['imgopthost'];
2309
        $opts                                        = autoptimizeImages::fetch_options();
2310
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2311
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2312
2313
        $markup = <<<MARKUP
2314
<img src='$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2315
MARKUP;
2316
2317
        $expected = <<<MARKUP
2318
<img src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$imgopthost/client/q_glossy,ret_img,w_300/$siteurl/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2319
MARKUP;
2320
        $instance = autoptimizeImages::instance();
2321
        $instance->set_options( $opts );
2322
        $actual = $instance->filter_optimize_images( $markup );
2323
        $this->assertEquals( $expected, $actual );
2324
    }
2325
2326
    /**
2327
     * Test image optimization in autoptimizeImages.php.
2328
     *
2329
     * case: picture tag
2330
     */
2331 View Code Duplication
    public function test_imgopt_picture()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2332
    {
2333
        $urls                                        = $this->get_urls();
2334
        $siteurl                                     = $urls['siteurl'];
2335
        $imgopthost                                  = $urls['imgopthost'];
2336
        $opts                                        = autoptimizeImages::fetch_options();
2337
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2338
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2339
2340
        $markup = <<<MARKUP
2341
<picture><source srcset="$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><img src="$siteurl/wp-content/image.jpg"/></picture>
2342
MARKUP;
2343
2344
        $expected = <<<MARKUP
2345
<picture><source srcset="$imgopthost/client/q_glossy,ret_img/$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><img src="$imgopthost/client/q_glossy,ret_img/$siteurl/wp-content/image.jpg"/></picture>
2346
MARKUP;
2347
        $instance = autoptimizeImages::instance();
2348
        $instance->set_options( $opts );
2349
        $actual = $instance->filter_optimize_images( $markup );
2350
        $this->assertEquals( $expected, $actual );
2351
    }
2352
2353
    /**
2354
     * Test image optimization & lazyload in autoptimizeImages.php.
2355
     *
2356
     * case: picture tag
2357
     */
2358
    public function test_imgopt_lazyload_picture()
2359
    {
2360
        $urls                                        = $this->get_urls();
2361
        $siteurl                                     = $urls['siteurl'];
2362
        $imgopthost                                  = $urls['imgopthost'];
2363
        $opts                                        = autoptimizeImages::fetch_options();
2364
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2365
        $opts['autoptimize_imgopt_checkbox_field_3'] = '1';
2366
2367
        $markup = <<<MARKUP
2368
<picture><source srcset="$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><img src="$siteurl/wp-content/image.jpg"/></picture>
2369
MARKUP;
2370
2371
        $expected = <<<MARKUP
2372
<picture><source data-srcset="$imgopthost/client/q_glossy,ret_img/$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><noscript><img src="$imgopthost/client/q_glossy,ret_img/$siteurl/wp-content/image.jpg"/></noscript><img class="lazyload" src='$imgopthost/client/q_lqip,ret_wait/$siteurl/wp-content/image.jpg' data-src="https://cdn.shortpixel.ai/client/q_glossy,ret_img/$siteurl/wp-content/image.jpg"/></picture>
2373
MARKUP;
2374
        $instance = autoptimizeImages::instance();
2375
        $instance->set_options( $opts );
2376
        $actual = $instance->filter_optimize_images( $markup );
2377
        $this->assertEquals( $expected, $actual );
2378
    }
2379
2380
    /**
2381
     * Test image optimization in autoptimizeImages.php.
2382
     *
2383
     * case: img with srcsets and lazyload
2384
     */
2385
    public function test_imgopt_with_lazyload()
2386
    {
2387
        $urls                                        = $this->get_urls();
2388
        $siteurl                                     = $urls['siteurl'];
2389
        $imgopthost                                  = $urls['imgopthost'];
2390
        $opts                                        = autoptimizeImages::fetch_options();
2391
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2392
        $opts['autoptimize_imgopt_checkbox_field_3'] = '1';
2393
2394
        $markup = <<<MARKUP
2395
<img src='$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2396
MARKUP;
2397
2398
        $expected = <<<MARKUP
2399
<noscript><img src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$imgopthost/client/q_glossy,ret_img,w_300/$siteurl/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" /></noscript><img class="lazyload" src='$imgopthost/client/q_lqip,ret_wait,w_400,h_200/$siteurl/wp-content/image.jpg' data-src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$siteurl/wp-content/image.jpg' width='400' height='200' data-srcset="$imgopthost/client/q_glossy,ret_img,w_300/$siteurl/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$siteurl/wp-content/image-600X300.jpg 600w" data-sizes="(max-width: 300px) 100vw, 300px" />
2400
MARKUP;
2401
2402
        $instance = autoptimizeImages::instance();
2403
        $instance->set_options( $opts );
2404
        $actual = $instance->filter_optimize_images( $markup );
2405
        $this->assertEquals( $expected, $actual );
2406
    }
2407
2408
    /**
2409
     * Test image optimization in autoptimizeImages.php.
2410
     *
2411
     * case: background image in a style attribute
2412
     */
2413 View Code Duplication
    public function test_imgopt_bgimg()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2414
    {
2415
        $urls                                        = $this->get_urls();
2416
        $siteurl                                     = $urls['siteurl'];
2417
        $imgopthost                                  = $urls['imgopthost'];
2418
        $opts                                        = autoptimizeImages::fetch_options();
2419
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2420
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2421
2422
        $markup = <<<MARKUP
2423
<div class="textwidget custom-html-widget"><div class="et_parallax_bg et_pb_parallax_css" style="height:200px; background-image: url($siteurl/wp-content/uploads/2018/05/DSC_1615-300x201.jpg);"></div>
2424
MARKUP;
2425
2426
        $expected = <<<MARKUP
2427
<div class="textwidget custom-html-widget"><div class="et_parallax_bg et_pb_parallax_css" style="height:200px; background-image: url($imgopthost/client/q_glossy,ret_img/$siteurl/wp-content/uploads/2018/05/DSC_1615-300x201.jpg);"></div>
2428
MARKUP;
2429
2430
        $instance = autoptimizeImages::instance();
2431
        $instance->set_options( $opts );
2432
        $actual = $instance->filter_optimize_images( $markup );
2433
        $this->assertEquals( $expected, $actual );
2434
    }
2435
2436
    /**
2437
     * Test lazyloading in autoptimizeImages.php.
2438
     *
2439
     * case: no image optimization
2440
     */
2441
    public function test_lazyload()
2442
    {
2443
        $urls                                        = $this->get_urls();
2444
        $siteurl                                     = $urls['siteurl'];
2445
        $imgopthost                                  = $urls['imgopthost'];
0 ignored issues
show
Unused Code introduced by
$imgopthost is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2446
        $opts                                        = autoptimizeImages::fetch_options();
2447
        $opts['autoptimize_imgopt_checkbox_field_3'] = '1';
2448
2449
        $markup = <<<MARKUP
2450
<img src='$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2451
MARKUP;
2452
2453
        $expected = <<<MARKUP
2454
<noscript><img src='$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" /></noscript><img class="lazyload" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20400%20200%22%3E%3C/svg%3E' data-src='$siteurl/wp-content/image.jpg' width='400' height='200' data-srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" data-sizes="(max-width: 300px) 100vw, 300px" />
2455
MARKUP;
2456
2457
        $instance = autoptimizeImages::instance();
2458
        $instance->set_options( $opts );
2459
        $actual = $instance->filter_lazyload_images( $markup );
2460
        $this->assertEquals( $expected, $actual );
2461
    }
2462
2463
    /**
2464
     * Test lazyload in autoptimizeImages.php.
2465
     *
2466
     * case: picture tag
2467
     */
2468 View Code Duplication
    public function test_picture_lazyload()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2469
    {
2470
        $urls                                        = $this->get_urls();
2471
        $siteurl                                     = $urls['siteurl'];
2472
        $imgopthost                                  = $urls['imgopthost'];
0 ignored issues
show
Unused Code introduced by
$imgopthost is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2473
        $opts                                        = autoptimizeImages::fetch_options();
2474
        $opts['autoptimize_imgopt_checkbox_field_3'] = '1';
2475
2476
        $markup = <<<MARKUP
2477
<picture><source srcset="$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><img src="$siteurl/wp-content/image.jpg"/></picture>
2478
MARKUP;
2479
2480
        $expected = <<<MARKUP
2481
<picture><source data-srcset="$siteurl/wp-content/image.jpg" media="(min-width: 800px)"><noscript><img src="$siteurl/wp-content/image.jpg"/></noscript><img class="lazyload" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="$siteurl/wp-content/image.jpg"/></picture>
2482
MARKUP;
2483
2484
        $instance = autoptimizeImages::instance();
2485
        $instance->set_options( $opts );
2486
        $actual = $instance->filter_lazyload_images( $markup );
2487
        $this->assertEquals( $expected, $actual );
2488
    }
2489
2490
    /**
2491
     * Test lazyload in autoptimizeImages.php.
2492
     *
2493
     * case: picture tag
2494
     */
2495
    public function test_bgimg_lazyload()
2496
    {
2497
        $urls                                        = $this->get_urls();
2498
        $siteurl                                     = $urls['siteurl'];
0 ignored issues
show
Unused Code introduced by
$siteurl is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2499
        $imgopthost                                  = $urls['imgopthost'];
0 ignored issues
show
Unused Code introduced by
$imgopthost is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2500
        $opts                                        = autoptimizeImages::fetch_options();
2501
        $opts['autoptimize_imgopt_checkbox_field_3'] = '1';
2502
2503
        $markup = <<<MARKUP
2504
<div id="just-an-id" style="height:250px;background-image: url(/wp-content/uploads/2018/05/DSC_1615-300x201.jpg);" class="hero background-image"></div>
2505
MARKUP;
2506
2507
        $expected = <<<MARKUP
2508
<div id="just-an-id" data-bg="/wp-content/uploads/2018/05/DSC_1615-300x201.jpg" style="height:250px;background-image: url(data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20500%20300%22%3E%3C/svg%3E);" class="lazyload hero background-image"></div>
2509
MARKUP;
2510
2511
        $instance = autoptimizeImages::instance();
2512
        $instance->set_options( $opts );
2513
        $actual = $instance->filter_lazyload_images( $markup );
2514
        $this->assertEquals( $expected, $actual );
2515
    }
2516
2517
    /**
2518
     * Test image optimization in autoptimizeImages.php.
2519
     *
2520
     * Exception case: image served by .php, should not be proxied.
2521
     */
2522 View Code Duplication
    public function test_imgopt_php()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2523
    {
2524
        $opts                                        = autoptimizeImages::fetch_options();
2525
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2526
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2527
2528
        $markup = <<<MARKUP
2529
<img src='/wp-content/plugins/imageplugin/image.php?id=16' width='400' height='200'>
2530
MARKUP;
2531
2532
        $instance = autoptimizeImages::instance();
2533
        $instance->set_options( $opts );
2534
        $actual = $instance->filter_optimize_images( $markup );
2535
2536
        // Expecting $markup since replacement should not happen.
2537
        $this->assertEquals( $markup, $actual );
2538
    }
2539
2540
    /**
2541
     * Test image optimization in autoptimizeImages.php.
2542
     *
2543
     * Alternate case: lazy loaded images with srcsets (using wp rocket variant HTML)
2544
     */
2545
    public function test_imgopt_alreadylazied()
2546
    {
2547
        $urls                                        = $this->get_urls();
2548
        $siteurl                                     = $urls['siteurl'];
2549
        $imgopthost                                  = $urls['imgopthost'];
2550
        $opts                                        = autoptimizeImages::fetch_options();
2551
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2552
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2553
2554
        $markup = <<<MARKUP
2555
<img src="data:image/gif;base64,R0lGODdhAQABAPAAAP///wAAACwAAAAAAQABAEACAkQBADs=" data-lazy-src='$siteurl/wp-content/image.jpg' width='400' height='200' data-lazy-srcset="$siteurl/wp-content/image-300X150.jpg 300w, $siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2556
MARKUP;
2557
2558
        $expected = <<<MARKUP
2559
<img src="data:image/gif;base64,R0lGODdhAQABAPAAAP///wAAACwAAAAAAQABAEACAkQBADs=" data-lazy-src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$siteurl/wp-content/image.jpg' width='400' height='200' data-lazy-srcset="$imgopthost/client/q_glossy,ret_img,w_300/$siteurl/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2560
MARKUP;
2561
2562
        $instance = autoptimizeImages::instance();
2563
        $instance->set_options( $opts );
2564
        $actual = $instance->filter_optimize_images( $markup );
2565
2566
        $this->assertEquals( $expected, $actual );
2567
    }
2568
2569
    /**
2570
     * Test image optimization when image urls have no explict host provided.
2571
     */
2572
    public function test_imgopt_url_normalize_root_relative()
2573
    {
2574
        $urls                                        = $this->get_urls();
2575
        $siteurl                                     = $urls['siteurl'];
2576
        $siteurlparsed                               = parse_url( $siteurl );
2577
        $sitedomain                                  = $siteurlparsed['scheme'] . '://' . $siteurlparsed['host'];
2578
        $imgopthost                                  = $urls['imgopthost'];
2579
        $opts                                        = autoptimizeImages::fetch_options();
2580
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2581
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2582
2583
        $markup = <<<MARKUP
2584
<img src='/wp-content/image.jpg' width='400' height='200' srcset="/wp-content/image-300X150.jpg 300w, /wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2585
MARKUP;
2586
2587
        $expected = <<<MARKUP
2588
<img src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$sitedomain/wp-content/image.jpg' width='400' height='200' srcset="$imgopthost/client/q_glossy,ret_img,w_300/$sitedomain/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$sitedomain/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2589
MARKUP;
2590
2591
        $instance = autoptimizeImages::instance();
2592
        $instance->set_options( $opts );
2593
        $actual = $instance->filter_optimize_images( $markup );
2594
2595
        $this->assertEquals( $expected, $actual );
2596
    }
2597
2598
    /**
2599
     * Test image optimization when image urls have a protocol-relative url.
2600
     */
2601
    public function test_imgopt_url_normalize_protocol_relative()
2602
    {
2603
        $urls                                        = $this->get_urls();
2604
        $siteurl                                     = $urls['siteurl'];
2605
        $prsiteurl                                   = $urls['prsiteurl'];
2606
        $imgopthost                                  = $urls['imgopthost'];
2607
        $opts                                        = autoptimizeImages::fetch_options();
2608
        $opts['autoptimize_imgopt_checkbox_field_1'] = '1';
2609
        $opts['autoptimize_imgopt_checkbox_field_3'] = '0';
2610
2611
        $markup = <<<MARKUP
2612
<img src='$prsiteurl/wp-content/image.jpg' width='400' height='200' srcset="$prsiteurl/wp-content/image-300X150.jpg 300w, $prsiteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2613
MARKUP;
2614
2615
        $expected = <<<MARKUP
2616
<img src='$imgopthost/client/q_glossy,ret_img,w_400,h_200/$siteurl/wp-content/image.jpg' width='400' height='200' srcset="$imgopthost/client/q_glossy,ret_img,w_300/$siteurl/wp-content/image-300X150.jpg 300w, $imgopthost/client/q_glossy,ret_img,w_600/$siteurl/wp-content/image-600X300.jpg 600w" sizes="(max-width: 300px) 100vw, 300px" />
2617
MARKUP;
2618
2619
        $instance = autoptimizeImages::instance();
2620
        $instance->set_options( $opts );
2621
        $actual = $instance->filter_optimize_images( $markup );
2622
2623
        $this->assertEquals( $expected, $actual );
2624
    }
2625
2626
    /**
2627
     * @dataProvider provider_str_is_valid_regex
2628
     */
2629
    public function test_str_is_valid_regex( $str, $expected )
2630
    {
2631
        $actual = autoptimizeUtils::str_is_valid_regex( $str );
2632
2633
        $this->assertEquals( $expected, $actual );
2634
    }
2635
2636
    public function provider_str_is_valid_regex()
2637
    {
2638
        return [
2639
            [ '<!--[if', false ],
2640
            [ '&lt;--[if', false ],
2641
            [ '/booya/i', true ],
2642
            [ '~Valid(Regular)Expression~', true ],
2643
        ];
2644
    }
2645
2646
    /**
2647
     * @dataProvider provider_protocol_relative_tests
2648
     */
2649
    public function test_is_protocol_relative( $str, $expected )
2650
    {
2651
        $actual = autoptimizeUtils::is_protocol_relative( $str );
2652
2653
        $this->assertEquals( $expected, $actual );
2654
    }
2655
2656
    public function provider_protocol_relative_tests()
2657
    {
2658
        return [
2659
            [ '//something-that-might-be-an-url-but-isnt-really', true ],
2660
            [ '', false ],
2661
            [ null, false ],
2662
            [ 'booya/i', false ],
2663
            [ '/root-relative', false ],
2664
            [ 'http://what.ever/', false ],
2665
            [ 'https://booya.kasha', false ],
2666
            [ '1/', false ],
2667
        ];
2668
    }
2669
2670 View Code Duplication
    public function test_css_minifier_unmatched_parens()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2671
    {
2672
        $css = <<<MARKUP
2673
img.centered, .aligncenter {
2674
    -webkit-box-shadow: none;
2675
    -moz-box-shadow: none;
2676
    box-shadow: none;
2677
MARKUP;
2678
2679
        $expected = 'img.centered,.aligncenter{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}';
2680
2681
        $instance = new autoptimizeStyles( $css );
2682
        $minified = $instance->run_minifier_on( $css );
2683
2684
        $this->assertEquals( $expected, $minified );
2685
    }
2686
2687
    public function test_css_font_names_mangling()
2688
    {
2689
        // Properly quoted font names dont get mangled.
2690
        $css      = 'h2{font-family:"Archivo Black"}';
2691
        $instance = new autoptimizeStyles( $css );
2692
        $actual   = $instance->run_minifier_on( $css );
2693
        $this->assertEquals( $css, $actual );
2694
2695
        // When not quoted, 'Black' used to become '#000', but not anymore :) ...
2696
        $css_unquoted = 'h2{font-family:Archivo Black;}';
2697
        $expected     = 'h2{font-family:Archivo Black}';
2698
        $instance     = new autoptimizeStyles( $css_unquoted );
2699
        $actual       = $instance->run_minifier_on( $css_unquoted );
2700
        $this->assertEquals( $expected, $actual );
2701
2702
        $css_unquoted = 'h1{font:italic 1.2em Fira White,serif}';
2703
        $instance     = new autoptimizeStyles( $css_unquoted );
2704
        $actual       = $instance->run_minifier_on( $css_unquoted );
2705
        $this->assertEquals( $css_unquoted, $actual );
2706
    }
2707
2708
    public function test_is_plugin_active_utils_wrapper()
2709
    {
2710
        // Our plugin is loaded via "muplugins_loaded" filter in tests/bootstrap.php.
2711
        $this->assertFalse( autoptimizeUtils::is_plugin_active( 'autoptimize/autoptimize.php' ) );
2712
        $this->assertFalse( autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' ) );
2713
    }
2714
2715
    public function test_jsminphp_string_literal_minification()
2716
    {
2717
        $js = '
2718
// comment
2719
`line
2720
break` + `he  llo`; foo`hel( \'\');lo`; `he\nl\`lo`; (`he${one + two}`)
2721
';
2722
2723
        $expected = '`line
2724
break`+`he  llo`;foo`hel( \'\');lo`;`he\nl\`lo`;(`he${one + two}`)';
2725
2726
        $actual = JSMin::minify( $js );
2727
        $this->assertEquals( $expected, $actual );
2728
    }
2729
2730
    /**
2731
     * Test preloading of resources (e.g. fonts).
2732
     */
2733 View Code Duplication
    public function test_preload()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2734
    {
2735
        $opts                                   = autoptimizeExtra::fetch_options();
2736
        $opts['autoptimize_extra_text_field_7'] = 'https://whatever.com/fonts/openfuttta.woff2, https://whatever.com/css/openfuttta.css';
2737
2738
        $markup = <<<MARKUP
2739
<html><link rel="stylesheet" href="xyz.css">
2740
MARKUP;
2741
2742
        $expected = <<<MARKUP
2743
<html><link rel="preload" href="https://whatever.com/fonts/openfuttta.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="https://whatever.com/css/openfuttta.css" as="style"><link rel="stylesheet" href="xyz.css">
2744
MARKUP;
2745
2746
        $instance = autoptimizeExtra::instance();
2747
        $instance->set_options( $opts );
2748
        $actual = $instance->filter_preload( $markup );
2749
        $this->assertEquals( $expected, $actual );
2750
    }
2751
2752
    /**
2753
     * Test network vs site settings: network only.
2754
     */
2755 View Code Duplication
    public function test_network_no_site_settings()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2756
    {
2757
        if ( is_multisite() ) {
2758
            define( 'TEST_MULTISITE_FORCE_AO_ON_NETWORK', true );
2759
            // set options through WordPress core methods.
2760
            update_option( 'autoptimize_js_exclude', 'site' );
2761
            update_network_option( get_main_network_id(), 'autoptimize_js_exclude', 'network' );
2762
            update_network_option( get_main_network_id(), 'autoptimize_enable_site_config', '' );
2763
2764
            // and then try fetching them through optionwrapper.
2765
            $expected = 'network';
2766
            $actual   = autoptimizeOptionWrapper::get_option( 'autoptimize_js_exclude' );
2767
            $this->assertEquals( $expected, $actual );
2768
        }
2769
    }
2770
2771
    /**
2772
     * Test network vs site settings; per site.
2773
     */
2774 View Code Duplication
    public function test_network_per_site_settings()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2775
    {
2776
        if ( is_multisite() ) {
2777
            // define of TEST_MULTISITE_FORCE_AO_ON_NETWORK not needed, done in previous test.
2778
            // set options through WordPress core methods.
2779
            update_option( 'autoptimize_js_exclude', 'site' );
2780
            update_network_option( get_main_network_id(), 'autoptimize_js_exclude', 'network' );
2781
            update_network_option( get_main_network_id(), 'autoptimize_enable_site_config', 'on' );
2782
2783
            // and then try fetching them through optionwrapper.
2784
            $expected = 'site';
2785
            $actual   = autoptimizeOptionWrapper::get_option( 'autoptimize_js_exclude' );
2786
            $this->assertEquals( $expected, $actual );
2787
        }
2788
    }
2789
}
2790