1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/test/test_font_family_parsing.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,285 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<head> 1.7 + <meta charset=utf-8> 1.8 + <title>Font family name parsing tests</title> 1.9 + <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com"> 1.10 + <link rel="help" href="http://www.w3.org/TR/css3-fonts/#font-family-prop" /> 1.11 + <link rel="help" href="http://www.w3.org/TR/css3-fonts/#font-prop" /> 1.12 + <meta name="assert" content="tests that valid font family names parse and invalid ones don't" /> 1.13 + <script type="text/javascript" src="/resources/testharness.js"></script> 1.14 + <script type="text/javascript" src="/resources/testharnessreport.js"></script> 1.15 + <style type="text/css"> 1.16 + </style> 1.17 +</head> 1.18 +<body> 1.19 +<div id="log"></div> 1.20 +<pre id="display"></pre> 1.21 +<style type="text/css" id="testbox"></style> 1.22 + 1.23 +<script type="text/javascript"> 1.24 + 1.25 +function fontProp(n, size, s1, s2) { return (s1 ? s1 + " " : "") + (s2 ? s2 + " " : "") + size + " " + n; } 1.26 +function font(n, size, s1, s2) { return "font: " + fontProp(n, size, s1, s2); } 1.27 + 1.28 +// testrules 1.29 +// namelist - font family list 1.30 +// invalid - true if declarations won't parse in either font-family or font 1.31 +// fontonly - only test with the 'font' property 1.32 +// single - namelist includes only a single name (@font-face rules only allow a single name) 1.33 + 1.34 +var testFontFamilyLists = [ 1.35 + 1.36 + /* basic syntax */ 1.37 + { namelist: "simple", single: true }, 1.38 + { namelist: "'simple'", single: true }, 1.39 + { namelist: '"simple"', single: true }, 1.40 + { namelist: "-simple", single: true }, 1.41 + { namelist: "_simple", single: true }, 1.42 + { namelist: "quite simple", single: true }, 1.43 + { namelist: "quite _simple", single: true }, 1.44 + { namelist: "quite -simple", single: true }, 1.45 + { namelist: "0simple", invalid: true, single: true }, 1.46 + { namelist: "simple!", invalid: true, single: true }, 1.47 + { namelist: "simple()", invalid: true, single: true }, 1.48 + { namelist: "quite@simple", invalid: true, single: true }, 1.49 + { namelist: "#simple", invalid: true, single: true }, 1.50 + { namelist: "quite 0simple", invalid: true, single: true }, 1.51 + { namelist: "納豆嫌い", single: true }, 1.52 + { namelist: "納豆嫌い, ick, patooey" }, 1.53 + { namelist: "ick, patooey, 納豆嫌い" }, 1.54 + { namelist: "納豆嫌い, 納豆大嫌い" }, 1.55 + { namelist: "納豆嫌い, 納豆大嫌い, 納豆本当に嫌い" }, 1.56 + { namelist: "納豆嫌い, 納豆大嫌い, 納豆本当に嫌い, 納豆は好みではない" }, 1.57 + { namelist: "arial, helvetica, sans-serif" }, 1.58 + { namelist: "arial, helvetica, 'times' new roman, sans-serif", invalid: true }, 1.59 + { namelist: "arial, helvetica, \"times\" new roman, sans-serif", invalid: true }, 1.60 + 1.61 + // bug 660397 - quotes contained within family names are not escaped 1.62 + // { namelist: "arial, helvetica, \"\\\"times new roman\", sans-serif" }, 1.63 + { namelist: "arial, helvetica, '\\\"times new roman', sans-serif" }, 1.64 + { namelist: "arial, helvetica, times 'new' roman, sans-serif", invalid: true }, 1.65 + { namelist: "arial, helvetica, times \"new\" roman, sans-serif", invalid: true }, 1.66 + // { namelist: "\"simple", invalid: true, single: true }, 1.67 + // { namelist: "\\\"simple", single: true }, 1.68 + // { namelist: "\"\\\"simple\"", single: true }, 1.69 + { namelist: "İsimple", single: true }, 1.70 + { namelist: "ßsimple", single: true }, 1.71 + { namelist: "ẙsimple", single: true }, 1.72 + 1.73 + /* escapes */ 1.74 + { namelist: "\\s imple", single: true }, 1.75 + { namelist: "\\073 imple", single: true }, 1.76 + 1.77 + // bug 475216 - css serialization doesn't escape characters that need escaping 1.78 + // { namelist: "\\035 simple", single: true }, 1.79 + { namelist: "sim\\035 ple", single: true }, 1.80 + // { namelist: "simple\\02cinitial", single: true }, 1.81 + // { namelist: "simple, \\02cinitial" }, 1.82 + // { namelist: "sim\\020 \\035 ple", single: true }, 1.83 + // { namelist: "sim\\020 5ple", single: true }, 1.84 + // { namelist: "\\;", single: true }, 1.85 + // { namelist: "\\;,\\;", single: true }, 1.86 + // { namelist: "\\,\\;", single: true }, 1.87 + // { namelist: "\\{", single: true }, 1.88 + // { namelist: "\\{\\;", single: true }, 1.89 + // { namelist: "\\}", single: true }, 1.90 + // { namelist: "\\}\\;", single: true }, 1.91 + // { namelist: "\\@simple", single: true }, 1.92 + // { namelist: "\\@simple\\;", single: true }, 1.93 + // { namelist: "\\@font-face", single: true }, 1.94 + // { namelist: "\\@font-face\\;", single: true }, 1.95 + // { namelist: "\\031 \\036 px", single: true }, 1.96 + // { namelist: "\\031 \\036 px", single: true }, 1.97 + { namelist: "\\1f4a9", single: true }, 1.98 + { namelist: "\\01f4a9", single: true }, 1.99 + { namelist: "\\0001f4a9", single: true }, 1.100 + { namelist: "\\AbAb", single: true }, 1.101 + 1.102 + /* keywords */ 1.103 + { namelist: "italic", single: true }, 1.104 + { namelist: "bold", single: true }, 1.105 + { namelist: "bold italic", single: true }, 1.106 + { namelist: "italic bold", single: true }, 1.107 + { namelist: "larger", single: true }, 1.108 + { namelist: "smaller", single: true }, 1.109 + { namelist: "bolder", single: true }, 1.110 + { namelist: "lighter", single: true }, 1.111 + { namelist: "default", invalid: true, fontonly: true, single: true }, 1.112 + { namelist: "initial", invalid: true, fontonly: true, single: true }, 1.113 + { namelist: "inherit", invalid: true, fontonly: true, single: true }, 1.114 + { namelist: "normal", single: true }, 1.115 + { namelist: "default, simple", invalid: true }, 1.116 + { namelist: "initial, simple", invalid: true }, 1.117 + { namelist: "inherit, simple", invalid: true }, 1.118 + { namelist: "normal, simple" }, 1.119 + { namelist: "simple, default", invalid: true }, 1.120 + { namelist: "simple, initial", invalid: true }, 1.121 + { namelist: "simple, inherit", invalid: true }, 1.122 + { namelist: "simple, default bongo" }, 1.123 + { namelist: "simple, initial bongo" }, 1.124 + { namelist: "simple, inherit bongo" }, 1.125 + { namelist: "simple, bongo default" }, 1.126 + { namelist: "simple, bongo initial" }, 1.127 + { namelist: "simple, bongo inherit" }, 1.128 + { namelist: "simple, normal" }, 1.129 + { namelist: "simple default", single: true }, 1.130 + { namelist: "simple initial", single: true }, 1.131 + { namelist: "simple inherit", single: true }, 1.132 + { namelist: "simple normal", single: true }, 1.133 + { namelist: "default simple", single: true }, 1.134 + { namelist: "initial simple", single: true }, 1.135 + { namelist: "inherit simple", single: true }, 1.136 + { namelist: "normal simple", single: true }, 1.137 + { namelist: "caption", single: true }, // these are keywords for the 'font' property but only when in the first position 1.138 + { namelist: "icon", single: true }, 1.139 + { namelist: "menu", single: true } 1.140 + 1.141 +]; 1.142 + 1.143 +if (SpecialPowers.getBoolPref("layout.css.unset-value.enabled")) { 1.144 + testFontFamilyLists.push( 1.145 + { namelist: "unset", invalid: true, fontonly: true, single: true }, 1.146 + { namelist: "unset, simple", invalid: true }, 1.147 + { namelist: "simple, unset", invalid: true }, 1.148 + { namelist: "simple, unset bongo" }, 1.149 + { namelist: "simple, bongo unset" }, 1.150 + { namelist: "simple unset", single: true }, 1.151 + { namelist: "unset simple", single: true }); 1.152 +} 1.153 + 1.154 +var gTest = 0; 1.155 + 1.156 +/* strip out just values */ 1.157 +function extractDecl(rule) 1.158 +{ 1.159 + var t = rule.replace(/[ \n]+/g, " "); 1.160 + t = t.replace(/.*{[ \n]*/, ""); 1.161 + t = t.replace(/[ \n]*}.*/, ""); 1.162 + return t; 1.163 +} 1.164 + 1.165 + 1.166 +function testStyleRuleParse(decl, invalid) { 1.167 + var sheet = document.styleSheets[1]; 1.168 + var rule = ".test" + gTest++ + " { " + decl + "; }"; 1.169 + 1.170 + while(sheet.cssRules.length > 0) { 1.171 + sheet.deleteRule(0); 1.172 + } 1.173 + 1.174 + // shouldn't throw but improper handling of punctuation may cause some parsers to throw 1.175 + try { 1.176 + sheet.insertRule(rule, 0); 1.177 + } catch (e) { 1.178 + assert_unreached("unexpected error with " + decl + " ==> " + e.name); 1.179 + } 1.180 + 1.181 + assert_equals(sheet.cssRules.length, 1, 1.182 + "strange number of rules (" + sheet.cssRules.length + ") with " + decl); 1.183 + 1.184 + var s = extractDecl(sheet.cssRules[0].cssText); 1.185 + 1.186 + if (invalid) { 1.187 + assert_equals(s, "", "rule declaration shouldn't parse - " + rule + " ==> " + s); 1.188 + } else { 1.189 + assert_not_equals(s, "", "rule declaration should parse - " + rule); 1.190 + 1.191 + // check that the serialization also parses 1.192 + var r = ".test" + gTest++ + " { " + s + " }"; 1.193 + while(sheet.cssRules.length > 0) { 1.194 + sheet.deleteRule(0); 1.195 + } 1.196 + try { 1.197 + sheet.insertRule(r, 0); 1.198 + } catch (e) { 1.199 + assert_unreached("exception occurred parsing serialized form of rule - " + rule + " ==> " + r + " " + e.name); 1.200 + } 1.201 + var s2 = extractDecl(sheet.cssRules[0].cssText); 1.202 + assert_not_equals(s2, "", "serialized form of rule should also parse - " + rule + " ==> " + r); 1.203 + } 1.204 +} 1.205 + 1.206 +var kDefaultFamilySetting = "onelittlepiggywenttomarket"; 1.207 + 1.208 +function testFontFamilySetterParse(namelist, invalid) { 1.209 + var el = document.getElementById("display"); 1.210 + 1.211 + el.style.fontFamily = kDefaultFamilySetting; 1.212 + var def = el.style.fontFamily; 1.213 + el.style.fontFamily = namelist; 1.214 + if (!invalid) { 1.215 + assert_not_equals(el.style.fontFamily, def, "fontFamily setter should parse - " + namelist); 1.216 + var parsed = el.style.fontFamily; 1.217 + el.style.fontFamily = kDefaultFamilySetting; 1.218 + el.style.fontFamily = parsed; 1.219 + assert_equals(el.style.fontFamily, parsed, "fontFamily setter should parse serialized form to identical serialization - " + parsed + " ==> " + el.style.fontFamily); 1.220 + } else { 1.221 + assert_equals(el.style.fontFamily, def, "fontFamily setter shouldn't parse - " + namelist); 1.222 + } 1.223 +} 1.224 + 1.225 +var kDefaultFontSetting = "16px onelittlepiggywenttomarket"; 1.226 + 1.227 +function testFontSetterParse(n, size, s1, s2, invalid) { 1.228 + var el = document.getElementById("display"); 1.229 + 1.230 + el.style.font = kDefaultFontSetting; 1.231 + var def = el.style.font; 1.232 + var fp = fontProp(n, size, s1, s2); 1.233 + el.style.font = fp; 1.234 + if (!invalid) { 1.235 + assert_not_equals(el.style.font, def, "font setter should parse - " + fp); 1.236 + var parsed = el.style.font; 1.237 + el.style.font = kDefaultFontSetting; 1.238 + el.style.font = parsed; 1.239 + assert_equals(el.style.font, parsed, "font setter should parse serialized form to identical serialization - " + parsed + " ==> " + el.style.font); 1.240 + } else { 1.241 + assert_equals(el.style.font, def, "font setter shouldn't parse - " + fp); 1.242 + } 1.243 +} 1.244 + 1.245 +var testFontVariations = [ 1.246 + { size: "16px" }, 1.247 + { size: "900px" }, 1.248 + { size: "900em" }, 1.249 + { size: "35%" }, 1.250 + { size: "7832.3%" }, 1.251 + { size: "xx-large" }, 1.252 + { size: "larger", s1: "lighter" }, 1.253 + { size: "16px", s1: "italic" }, 1.254 + { size: "16px", s1: "italic", s2: "bold" }, 1.255 + { size: "smaller", s1: "normal" }, 1.256 + { size: "16px", s1: "normal", s2: "normal" }, 1.257 + { size: "16px", s1: "400", s2: "normal" }, 1.258 + { size: "16px", s1: "bolder", s2: "oblique" } 1.259 +]; 1.260 + 1.261 +function testFamilyNameParsing() { 1.262 + var i; 1.263 + for (i = 0; i < testFontFamilyLists.length; i++) { 1.264 + var tst = testFontFamilyLists[i]; 1.265 + var n = tst.namelist; 1.266 + var t; 1.267 + 1.268 + if (!tst.fontonly) { 1.269 + t = "font-family: " + n; 1.270 + test(function() { testStyleRuleParse(t, tst.invalid); }, t); 1.271 + test(function() { testFontFamilySetterParse(n, tst.invalid); }, t + " (setter)"); 1.272 + } 1.273 + 1.274 + var v; 1.275 + for (v = 0; v < testFontVariations.length; v++) { 1.276 + var f = testFontVariations[v]; 1.277 + t = font(n, f.size, f.s1, f.s2); 1.278 + test(function() { testStyleRuleParse(t, tst.invalid); }, t); 1.279 + test(function() { testFontSetterParse(n, f.size, f.s1, f.s2, tst.invalid); }, t + " (setter)"); 1.280 + } 1.281 + } 1.282 +} 1.283 + 1.284 +testFamilyNameParsing(); 1.285 + 1.286 +</script> 1.287 +</body> 1.288 +</html>