1# Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions 5# are met: 6# 7# 1. Redistributions of source code must retain the above 8# copyright notice, this list of conditions and the following 9# disclaimer. 10# 2. Redistributions in binary form must reproduce the above 11# copyright notice, this list of conditions and the following 12# disclaimer in the documentation and/or other materials 13# provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY 16# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 19# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 20# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 24# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 25# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27 28import os 29import re 30import unittest 31 32from webkitpy.common.host import Host 33from webkitpy.common.system.outputcapture import OutputCapture 34from webkitpy.common.webkit_finder import WebKitFinder 35from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup 36from webkitpy.w3c.test_converter import _W3CTestConverter 37 38DUMMY_FILENAME = 'dummy.html' 39DUMMY_PATH = 'dummy/testharness/path' 40 41class W3CTestConverterTest(unittest.TestCase): 42 43 # FIXME: When we move to using a MockHost, this method should be removed, since 44 # then we can just pass in a dummy dir path 45 def fake_dir_path(self, dirname): 46 filesystem = Host().filesystem 47 webkit_root = WebKitFinder(filesystem).webkit_base() 48 return filesystem.abspath(filesystem.join(webkit_root, "LayoutTests", "css", dirname)) 49 50 def test_read_prefixed_property_list(self): 51 """ Tests that the current list of properties requiring the -webkit- prefix load correctly """ 52 53 # FIXME: We should be passing in a MockHost here ... 54 converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME) 55 prop_list = converter.prefixed_properties 56 self.assertTrue(prop_list, 'No prefixed properties found') 57 58 def test_convert_for_webkit_nothing_to_convert(self): 59 """ Tests convert_for_webkit() using a basic test that has nothing to convert """ 60 61 test_html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 62"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 63<html xmlns="http://www.w3.org/1999/xhtml"> 64<head> 65<title>CSS Test: DESCRIPTION OF TEST</title> 66<link rel="author" title="NAME_OF_AUTHOR" 67href="mailto:EMAIL OR http://CONTACT_PAGE"/> 68<link rel="help" href="RELEVANT_SPEC_SECTION"/> 69<meta name="assert" content="TEST ASSERTION"/> 70<style type="text/css"><![CDATA[ 71CSS FOR TEST 72]]></style> 73</head> 74<body> 75CONTENT OF TEST 76</body> 77</html> 78""" 79 converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME) 80 81 oc = OutputCapture() 82 oc.capture_output() 83 try: 84 converter.feed(test_html) 85 converter.close() 86 converted = converter.output() 87 finally: 88 oc.restore_output() 89 90 self.verify_no_conversion_happened(converted, test_html) 91 92 def test_convert_for_webkit_harness_only(self): 93 """ Tests convert_for_webkit() using a basic JS test that uses testharness.js only and has no prefixed properties """ 94 95 test_html = """<head> 96<link href="/resources/testharness.css" rel="stylesheet" type="text/css"> 97<script src="/resources/testharness.js"></script> 98</head> 99""" 100 fake_dir_path = self.fake_dir_path("harnessonly") 101 converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME) 102 converter.feed(test_html) 103 converter.close() 104 converted = converter.output() 105 106 self.verify_conversion_happened(converted) 107 self.verify_test_harness_paths(converter, converted[1], fake_dir_path, 1, 1) 108 self.verify_prefixed_properties(converted, []) 109 110 def test_convert_for_webkit_properties_only(self): 111 """ Tests convert_for_webkit() using a test that has 2 prefixed properties: 1 in a style block + 1 inline style """ 112 113 test_html = """<html> 114<head> 115<link href="/resources/testharness.css" rel="stylesheet" type="text/css"> 116<script src="/resources/testharness.js"></script> 117<style type="text/css"> 118 119#block1 { @test0@: propvalue; } 120 121</style> 122</head> 123<body> 124<div id="elem1" style="@test1@: propvalue;"></div> 125</body> 126</html> 127""" 128 fake_dir_path = self.fake_dir_path('harnessandprops') 129 converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME) 130 test_content = self.generate_test_content(converter.prefixed_properties, 1, test_html) 131 132 oc = OutputCapture() 133 oc.capture_output() 134 try: 135 converter.feed(test_content[1]) 136 converter.close() 137 converted = converter.output() 138 finally: 139 oc.restore_output() 140 141 self.verify_conversion_happened(converted) 142 self.verify_test_harness_paths(converter, converted[1], fake_dir_path, 1, 1) 143 self.verify_prefixed_properties(converted, test_content[0]) 144 145 def test_convert_for_webkit_harness_and_properties(self): 146 """ Tests convert_for_webkit() using a basic JS test that uses testharness.js and testharness.css and has 4 prefixed properties: 3 in a style block + 1 inline style """ 147 148 test_html = """<html> 149<head> 150<link href="/resources/testharness.css" rel="stylesheet" type="text/css"> 151<script src="/resources/testharness.js"></script> 152<style type="text/css"> 153 154#block1 { @test0@: propvalue; } 155#block2 { @test1@: propvalue; } 156#block3 { @test2@: propvalue; } 157 158</style> 159</head> 160<body> 161<div id="elem1" style="@test3@: propvalue;"></div> 162</body> 163</html> 164""" 165 fake_dir_path = self.fake_dir_path('harnessandprops') 166 converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME) 167 168 oc = OutputCapture() 169 oc.capture_output() 170 try: 171 test_content = self.generate_test_content(converter.prefixed_properties, 2, test_html) 172 converter.feed(test_content[1]) 173 converter.close() 174 converted = converter.output() 175 finally: 176 oc.restore_output() 177 178 self.verify_conversion_happened(converted) 179 self.verify_test_harness_paths(converter, converted[1], fake_dir_path, 1, 1) 180 self.verify_prefixed_properties(converted, test_content[0]) 181 182 def test_convert_test_harness_paths(self): 183 """ Tests convert_testharness_paths() with a test that uses all three testharness files """ 184 185 test_html = """<head> 186<link href="/resources/testharness.css" rel="stylesheet" type="text/css"> 187<script src="/resources/testharness.js"></script> 188<script src="/resources/testharnessreport.js"></script> 189</head> 190""" 191 fake_dir_path = self.fake_dir_path('testharnesspaths') 192 converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME) 193 194 oc = OutputCapture() 195 oc.capture_output() 196 try: 197 converter.feed(test_html) 198 converter.close() 199 converted = converter.output() 200 finally: 201 oc.restore_output() 202 203 self.verify_conversion_happened(converted) 204 self.verify_test_harness_paths(converter, converted[1], fake_dir_path, 2, 1) 205 206 def test_convert_vendor_prefix_js_paths(self): 207 test_html = """<head> 208<script src="/common/vendor-prefix.js"> 209</head> 210""" 211 fake_dir_path = self.fake_dir_path('adapterjspaths') 212 converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME) 213 214 oc = OutputCapture() 215 oc.capture_output() 216 try: 217 converter.feed(test_html) 218 converter.close() 219 converted = converter.output() 220 finally: 221 oc.restore_output() 222 223 new_html = BeautifulSoup(converted[1]) 224 225 # Verify the original paths are gone, and the new paths are present. 226 orig_path_pattern = re.compile('\"/common/vendor-prefix.js') 227 self.assertEquals(len(new_html.findAll(src=orig_path_pattern)), 0, 'vendor-prefix.js path was not converted') 228 229 resources_dir = converter.path_from_webkit_root("LayoutTests", "resources") 230 new_relpath = os.path.relpath(resources_dir, fake_dir_path) 231 relpath_pattern = re.compile(new_relpath) 232 self.assertEquals(len(new_html.findAll(src=relpath_pattern)), 1, 'vendor-prefix.js relative path not correct') 233 234 def test_convert_prefixed_properties(self): 235 """ Tests convert_prefixed_properties() file that has 20 properties requiring the -webkit- prefix: 236 10 in one style block + 5 in another style 237 block + 5 inline styles, including one with multiple prefixed properties. 238 The properties in the test content are in all sorts of wack formatting. 239 """ 240 241 test_html = """<html> 242<style type="text/css"><![CDATA[ 243 244.block1 { 245 width: 300px; 246 height: 300px 247} 248 249.block2 { 250 @test0@: propvalue; 251} 252 253.block3{@test1@: propvalue;} 254 255.block4 { @test2@:propvalue; } 256 257.block5{ @test3@ :propvalue; } 258 259#block6 { @test4@ : propvalue; } 260 261#block7 262{ 263 @test5@: propvalue; 264} 265 266#block8 { @test6@: propvalue; } 267 268#block9:pseudo 269{ 270 271 @test7@: propvalue; 272 @test8@: propvalue propvalue propvalue;; 273} 274 275]]></style> 276</head> 277<body> 278 <div id="elem1" style="@test9@: propvalue;"></div> 279 <div id="elem2" style="propname: propvalue; @test10@ : propvalue; propname:propvalue;"></div> 280 <div id="elem2" style="@test11@: propvalue; @test12@ : propvalue; @test13@ :propvalue;"></div> 281 <div id="elem3" style="@test14@:propvalue"></div> 282</body> 283<style type="text/css"><![CDATA[ 284 285.block10{ @test15@: propvalue; } 286.block11{ @test16@: propvalue; } 287.block12{ @test17@: propvalue; } 288#block13:pseudo 289{ 290 @test18@: propvalue; 291 @test19@: propvalue; 292} 293 294]]></style> 295</html> 296""" 297 converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME) 298 test_content = self.generate_test_content(converter.prefixed_properties, 20, test_html) 299 300 oc = OutputCapture() 301 oc.capture_output() 302 try: 303 converter.feed(test_content[1]) 304 converter.close() 305 converted = converter.output() 306 finally: 307 oc.restore_output() 308 309 self.verify_conversion_happened(converted) 310 self.verify_prefixed_properties(converted, test_content[0]) 311 312 def test_hides_all_instructions_for_manual_testers(self): 313 test_html = """<body> 314<h1 class="instructions">Hello manual tester!</h1> 315<p class="instructions some_other_class">This is how you run this test.</p> 316<p style="willbeoverwritten" class="instructions">...</p> 317<doesntmatterwhichtagitis class="some_other_class instructions">...</p> 318<p>Legit content may contain the instructions string</p> 319</body> 320""" 321 expected_test_html = """<body> 322<h1 class="instructions" style="display:none">Hello manual tester!</h1> 323<p class="instructions some_other_class" style="display:none">This is how you run this test.</p> 324<p class="instructions" style="display:none">...</p> 325<doesntmatterwhichtagitis class="some_other_class instructions" style="display:none">...</p> 326<p>Legit content may contain the instructions string</p> 327</body> 328""" 329 converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME) 330 331 oc = OutputCapture() 332 oc.capture_output() 333 try: 334 converter.feed(test_html) 335 converter.close() 336 converted = converter.output() 337 finally: 338 oc.restore_output() 339 340 self.assertEqual(converted[1], expected_test_html) 341 342 def verify_conversion_happened(self, converted): 343 self.assertTrue(converted, "conversion didn't happen") 344 345 def verify_no_conversion_happened(self, converted, original): 346 self.assertEqual(converted[1], original, 'test should not have been converted') 347 348 def verify_test_harness_paths(self, converter, converted, test_path, num_src_paths, num_href_paths): 349 if isinstance(converted, basestring): 350 converted = BeautifulSoup(converted) 351 352 resources_dir = converter.path_from_webkit_root("LayoutTests", "resources") 353 354 # Verify the original paths are gone, and the new paths are present. 355 orig_path_pattern = re.compile('\"/resources/testharness') 356 self.assertEquals(len(converted.findAll(src=orig_path_pattern)), 0, 'testharness src path was not converted') 357 self.assertEquals(len(converted.findAll(href=orig_path_pattern)), 0, 'testharness href path was not converted') 358 359 new_relpath = os.path.relpath(resources_dir, test_path) 360 relpath_pattern = re.compile(new_relpath) 361 self.assertEquals(len(converted.findAll(src=relpath_pattern)), num_src_paths, 'testharness src relative path not correct') 362 self.assertEquals(len(converted.findAll(href=relpath_pattern)), num_href_paths, 'testharness href relative path not correct') 363 364 def verify_prefixed_properties(self, converted, test_properties): 365 self.assertEqual(len(set(converted[0])), len(set(test_properties)), 'Incorrect number of properties converted') 366 for test_prop in test_properties: 367 self.assertTrue((test_prop in converted[1]), 'Property ' + test_prop + ' not found in converted doc') 368 369 def generate_test_content(self, full_property_list, num_test_properties, html): 370 """Inserts properties requiring a -webkit- prefix into the content, replacing \'@testXX@\' with a property.""" 371 test_properties = [] 372 count = 0 373 while count < num_test_properties: 374 test_properties.append(full_property_list[count]) 375 count += 1 376 377 # Replace the tokens in the testhtml with the test properties. Walk backward 378 # through the list to replace the double-digit tokens first 379 index = len(test_properties) - 1 380 while index >= 0: 381 # Use the unprefixed version 382 test_prop = test_properties[index].replace('-webkit-', '') 383 # Replace the token 384 html = html.replace('@test' + str(index) + '@', test_prop) 385 index -= 1 386 387 return (test_properties, html) 388