Merge "Rename wfIsHipHop() to wfIsHHVM()"
[lhc/web/wiklou.git] / tests / phpunit / structure / ResourcesTest.php
1 <?php
2 /**
3 * Sanity checks for making sure registered resources are sane.
4 *
5 * @file
6 * @author Antoine Musso
7 * @author Niklas Laxström
8 * @author Santhosh Thottingal
9 * @author Timo Tijhof
10 * @copyright © 2012, Antoine Musso
11 * @copyright © 2012, Niklas Laxström
12 * @copyright © 2012, Santhosh Thottingal
13 * @copyright © 2012, Timo Tijhof
14 *
15 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
16 */
17 class ResourcesTest extends MediaWikiTestCase {
18
19 /**
20 * @dataProvider provideResourceFiles
21 */
22 public function testFileExistence( $filename, $module, $resource ) {
23 $this->assertFileExists( $filename,
24 "File '$resource' referenced by '$module' must exist."
25 );
26 }
27
28 /**
29 * @dataProvider provideMediaStylesheets
30 */
31 public function testStyleMedia( $moduleName, $media, $filename, $css ) {
32 $cssText = CSSMin::minify( $css->cssText );
33
34 $this->assertTrue( strpos( $cssText, '@media' ) === false, 'Stylesheets should not both specify "media" and contain @media' );
35 }
36
37 /**
38 * Get all registered modules from ResouceLoader.
39 */
40 protected static function getAllModules() {
41 global $wgEnableJavaScriptTest;
42
43 // Test existance of test suite files as well
44 // (can't use setUp or setMwGlobals because providers are static)
45 $org_wgEnableJavaScriptTest = $wgEnableJavaScriptTest;
46 $wgEnableJavaScriptTest = true;
47
48 // Initialize ResourceLoader
49 $rl = new ResourceLoader();
50
51 $modules = array();
52
53 foreach ( $rl->getModuleNames() as $moduleName ) {
54 $modules[$moduleName] = $rl->getModule( $moduleName );
55 }
56
57 // Restore settings
58 $wgEnableJavaScriptTest = $org_wgEnableJavaScriptTest;
59
60 return array(
61 'modules' => $modules,
62 'resourceloader' => $rl,
63 'context' => new ResourceLoaderContext( $rl, new FauxRequest() )
64 );
65 }
66
67 /**
68 * Get all stylesheet files from modules that are an instance of
69 * ResourceLoaderFileModule (or one of its subclasses).
70 */
71 public static function provideMediaStylesheets() {
72 $data = self::getAllModules();
73 $cases = array();
74
75 foreach ( $data['modules'] as $moduleName => $module ) {
76 if ( !$module instanceof ResourceLoaderFileModule ) {
77 continue;
78 }
79
80 $reflectedModule = new ReflectionObject( $module );
81
82 $getStyleFiles = $reflectedModule->getMethod( 'getStyleFiles' );
83 $getStyleFiles->setAccessible( true );
84
85 $readStyleFile = $reflectedModule->getMethod( 'readStyleFile' );
86 $readStyleFile->setAccessible( true );
87
88 $styleFiles = $getStyleFiles->invoke( $module, $data['context'] );
89
90 $flip = $module->getFlip( $data['context'] );
91
92 foreach ( $styleFiles as $media => $files ) {
93 if ( $media && $media !== 'all' ) {
94 foreach ( $files as $file ) {
95 $cases[] = array(
96 $moduleName,
97 $media,
98 $file,
99 // XXX: Wrapped in an object to keep it out of PHPUnit output
100 (object) array( 'cssText' => $readStyleFile->invoke( $module, $file, $flip ) ),
101 );
102 }
103 }
104 }
105 }
106
107 return $cases;
108 }
109
110 /**
111 * Get all resource files from modules that are an instance of
112 * ResourceLoaderFileModule (or one of its subclasses).
113 *
114 * Since the raw data is stored in protected properties, we have to
115 * overrride this through ReflectionObject methods.
116 */
117 public static function provideResourceFiles() {
118 $data = self::getAllModules();
119 $cases = array();
120
121 // See also ResourceLoaderFileModule::__construct
122 $filePathProps = array(
123 // Lists of file paths
124 'lists' => array(
125 'scripts',
126 'debugScripts',
127 'loaderScripts',
128 'styles',
129 ),
130
131 // Collated lists of file paths
132 'nested-lists' => array(
133 'languageScripts',
134 'skinScripts',
135 'skinStyles',
136 ),
137 );
138
139 foreach ( $data['modules'] as $moduleName => $module ) {
140 if ( !$module instanceof ResourceLoaderFileModule ) {
141 continue;
142 }
143
144 $reflectedModule = new ReflectionObject( $module );
145
146 $files = array();
147
148 foreach ( $filePathProps['lists'] as $propName ) {
149 $property = $reflectedModule->getProperty( $propName );
150 $property->setAccessible( true );
151 $list = $property->getValue( $module );
152 foreach ( $list as $key => $value ) {
153 // 'scripts' are numeral arrays.
154 // 'styles' can be numeral or associative.
155 // In case of associative the key is the file path
156 // and the value is the 'media' attribute.
157 if ( is_int( $key ) ) {
158 $files[] = $value;
159 } else {
160 $files[] = $key;
161 }
162 }
163 }
164
165 foreach ( $filePathProps['nested-lists'] as $propName ) {
166 $property = $reflectedModule->getProperty( $propName );
167 $property->setAccessible( true );
168 $lists = $property->getValue( $module );
169 foreach ( $lists as $list ) {
170 foreach ( $list as $key => $value ) {
171 // We need the same filter as for 'lists',
172 // due to 'skinStyles'.
173 if ( is_int( $key ) ) {
174 $files[] = $value;
175 } else {
176 $files[] = $key;
177 }
178 }
179 }
180 }
181
182 // Get method for resolving the paths to full paths
183 $method = $reflectedModule->getMethod( 'getLocalPath' );
184 $method->setAccessible( true );
185
186 // Populate cases
187 foreach ( $files as $file ) {
188 $cases[] = array(
189 $method->invoke( $module, $file ),
190 $moduleName,
191 $file,
192 );
193 }
194 }
195
196
197 return $cases;
198 }
199 }