test_font_family_parsing.html (10864B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset=utf-8> 5 <title>Font family name parsing tests</title> 6 <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com"> 7 <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-family-prop" /> 8 <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-prop" /> 9 <meta name="assert" content="tests that valid font family names parse and invalid ones don't" /> 10 <script type="text/javascript" src="/resources/testharness.js"></script> 11 <script type="text/javascript" src="/resources/testharnessreport.js"></script> 12 <style type="text/css"> 13 </style> 14 </head> 15 <body> 16 <div id="log"></div> 17 <pre id="display"></pre> 18 <style type="text/css" id="testbox"></style> 19 20 <script type="text/javascript"> 21 22 function fontProp(n, size, s1, s2) { return (s1 ? s1 + " " : "") + (s2 ? s2 + " " : "") + size + " " + n; } 23 function font(n, size, s1, s2) { return "font: " + fontProp(n, size, s1, s2); } 24 25 // testrules 26 // namelist - font family list 27 // invalid - true if declarations won't parse in either font-family or font 28 // fontonly - only test with the 'font' property 29 // single - namelist includes only a single name (@font-face rules only allow a single name) 30 31 var testFontFamilyLists = [ 32 33 /* basic syntax */ 34 { namelist: "simple", single: true }, 35 { namelist: "'simple'", single: true }, 36 { namelist: '"simple"', single: true }, 37 { namelist: "-simple", single: true }, 38 { namelist: "_simple", single: true }, 39 { namelist: "quite simple", single: true }, 40 { namelist: "quite _simple", single: true }, 41 { namelist: "quite -simple", single: true }, 42 { namelist: "0simple", invalid: true, single: true }, 43 { namelist: "simple!", invalid: true, single: true }, 44 { namelist: "simple()", invalid: true, single: true }, 45 { namelist: "quite@simple", invalid: true, single: true }, 46 { namelist: "#simple", invalid: true, single: true }, 47 { namelist: "quite 0simple", invalid: true, single: true }, 48 { namelist: "納豆嫌い", single: true }, 49 { namelist: "納豆嫌い, ick, patooey" }, 50 { namelist: "ick, patooey, 納豆嫌い" }, 51 { namelist: "納豆嫌い, 納豆大嫌い" }, 52 { namelist: "納豆嫌い, 納豆大嫌い, 納豆本当に嫌い" }, 53 { namelist: "納豆嫌い, 納豆大嫌い, 納豆本当に嫌い, 納豆は好みではない" }, 54 { namelist: "arial, helvetica, sans-serif" }, 55 { namelist: "arial, helvetica, 'times' new roman, sans-serif", invalid: true }, 56 { namelist: "arial, helvetica, \"times\" new roman, sans-serif", invalid: true }, 57 58 // bug 660397 - quotes contained within family names are not escaped 59 // { namelist: "arial, helvetica, \"\\\"times new roman\", sans-serif" }, 60 { namelist: "arial, helvetica, '\\\"times new roman', sans-serif" }, 61 { namelist: "arial, helvetica, times 'new' roman, sans-serif", invalid: true }, 62 { namelist: "arial, helvetica, times \"new\" roman, sans-serif", invalid: true }, 63 // { namelist: "\"simple", invalid: true, single: true }, 64 // { namelist: "\\\"simple", single: true }, 65 // { namelist: "\"\\\"simple\"", single: true }, 66 { namelist: "İsimple", single: true }, 67 { namelist: "ßsimple", single: true }, 68 { namelist: "ẙsimple", single: true }, 69 70 /* escapes */ 71 { namelist: "\\s imple", single: true }, 72 { namelist: "\\073 imple", single: true }, 73 74 // bug 475216 - css serialization doesn't escape characters that need escaping 75 // { namelist: "\\035 simple", single: true }, 76 { namelist: "sim\\035 ple", single: true }, 77 // { namelist: "simple\\02cinitial", single: true }, 78 // { namelist: "simple, \\02cinitial" }, 79 // { namelist: "sim\\020 \\035 ple", single: true }, 80 // { namelist: "sim\\020 5ple", single: true }, 81 // { namelist: "\\;", single: true }, 82 // { namelist: "\\;,\\;", single: true }, 83 // { namelist: "\\,\\;", single: true }, 84 // { namelist: "\\{", single: true }, 85 // { namelist: "\\{\\;", single: true }, 86 // { namelist: "\\}", single: true }, 87 // { namelist: "\\}\\;", single: true }, 88 // { namelist: "\\@simple", single: true }, 89 // { namelist: "\\@simple\\;", single: true }, 90 // { namelist: "\\@font-face", single: true }, 91 // { namelist: "\\@font-face\\;", single: true }, 92 // { namelist: "\\031 \\036 px", single: true }, 93 // { namelist: "\\031 \\036 px", single: true }, 94 { namelist: "\\1f4a9", single: true }, 95 { namelist: "\\01f4a9", single: true }, 96 { namelist: "\\0001f4a9", single: true }, 97 { namelist: "\\AbAb", single: true }, 98 99 /* keywords */ 100 { namelist: "italic", single: true }, 101 { namelist: "bold", single: true }, 102 { namelist: "bold italic", single: true }, 103 { namelist: "italic bold", single: true }, 104 { namelist: "larger", single: true }, 105 { namelist: "smaller", single: true }, 106 { namelist: "bolder", single: true }, 107 { namelist: "lighter", single: true }, 108 { namelist: "default", invalid: true, fontonly: true, single: true }, 109 { namelist: "initial", invalid: true, fontonly: true, single: true }, 110 { namelist: "inherit", invalid: true, fontonly: true, single: true }, 111 { namelist: "normal", single: true }, 112 { namelist: "default, simple", invalid: true }, 113 { namelist: "initial, simple", invalid: true }, 114 { namelist: "inherit, simple", invalid: true }, 115 { namelist: "normal, simple" }, 116 { namelist: "simple, default", invalid: true }, 117 { namelist: "simple, initial", invalid: true }, 118 { namelist: "simple, inherit", invalid: true }, 119 { namelist: "simple, default bongo" }, 120 { namelist: "simple, initial bongo" }, 121 { namelist: "simple, inherit bongo" }, 122 { namelist: "simple, bongo default" }, 123 { namelist: "simple, bongo initial" }, 124 { namelist: "simple, bongo inherit" }, 125 { namelist: "simple, normal" }, 126 { namelist: "simple default", single: true }, 127 { namelist: "simple initial", single: true }, 128 { namelist: "simple inherit", single: true }, 129 { namelist: "simple normal", single: true }, 130 { namelist: "default simple", single: true }, 131 { namelist: "initial simple", single: true }, 132 { namelist: "inherit simple", single: true }, 133 { namelist: "normal simple", single: true }, 134 { namelist: "caption", single: true }, // these are keywords for the 'font' property but only when in the first position 135 { namelist: "icon", single: true }, 136 { namelist: "menu", single: true }, 137 138 /* Unset */ 139 { namelist: "unset", invalid: true, fontonly: true, single: true }, 140 { namelist: "unset, simple", invalid: true }, 141 { namelist: "simple, unset", invalid: true }, 142 { namelist: "simple, unset bongo" }, 143 { namelist: "simple, bongo unset" }, 144 { namelist: "simple unset", single: true }, 145 { namelist: "unset simple", single: true }, 146 ]; 147 148 var gTest = 0; 149 150 /* strip out just values */ 151 function extractDecl(rule) 152 { 153 var t = rule.replace(/[ \n]+/g, " "); 154 t = t.replace(/.*{[ \n]*/, ""); 155 t = t.replace(/[ \n]*}.*/, ""); 156 return t; 157 } 158 159 160 function testStyleRuleParse(decl, invalid) { 161 var sheet = document.styleSheets[1]; 162 var rule = ".test" + gTest++ + " { " + decl + "; }"; 163 164 while(sheet.cssRules.length > 0) { 165 sheet.deleteRule(0); 166 } 167 168 // shouldn't throw but improper handling of punctuation may cause some parsers to throw 169 try { 170 sheet.insertRule(rule, 0); 171 } catch (e) { 172 assert_unreached("unexpected error with " + decl + " ==> " + e.name); 173 } 174 175 assert_equals(sheet.cssRules.length, 1, 176 "strange number of rules (" + sheet.cssRules.length + ") with " + decl); 177 178 var s = extractDecl(sheet.cssRules[0].cssText); 179 180 if (invalid) { 181 assert_equals(s, "", "rule declaration shouldn't parse - " + rule + " ==> " + s); 182 } else { 183 assert_not_equals(s, "", "rule declaration should parse - " + rule); 184 185 // check that the serialization also parses 186 var r = ".test" + gTest++ + " { " + s + " }"; 187 while(sheet.cssRules.length > 0) { 188 sheet.deleteRule(0); 189 } 190 try { 191 sheet.insertRule(r, 0); 192 } catch (e) { 193 assert_unreached("exception occurred parsing serialized form of rule - " + rule + " ==> " + r + " " + e.name); 194 } 195 var s2 = extractDecl(sheet.cssRules[0].cssText); 196 assert_not_equals(s2, "", "serialized form of rule should also parse - " + rule + " ==> " + r); 197 } 198 } 199 200 var kDefaultFamilySetting = "onelittlepiggywenttomarket"; 201 202 function testFontFamilySetterParse(namelist, invalid) { 203 var el = document.getElementById("display"); 204 205 el.style.fontFamily = kDefaultFamilySetting; 206 var def = el.style.fontFamily; 207 el.style.fontFamily = namelist; 208 if (!invalid) { 209 assert_not_equals(el.style.fontFamily, def, "fontFamily setter should parse - " + namelist); 210 var parsed = el.style.fontFamily; 211 el.style.fontFamily = kDefaultFamilySetting; 212 el.style.fontFamily = parsed; 213 assert_equals(el.style.fontFamily, parsed, "fontFamily setter should parse serialized form to identical serialization - " + parsed + " ==> " + el.style.fontFamily); 214 } else { 215 assert_equals(el.style.fontFamily, def, "fontFamily setter shouldn't parse - " + namelist); 216 } 217 } 218 219 var kDefaultFontSetting = "16px onelittlepiggywenttomarket"; 220 221 function testFontSetterParse(n, size, s1, s2, invalid) { 222 var el = document.getElementById("display"); 223 224 el.style.font = kDefaultFontSetting; 225 var def = el.style.font; 226 var fp = fontProp(n, size, s1, s2); 227 el.style.font = fp; 228 if (!invalid) { 229 assert_not_equals(el.style.font, def, "font setter should parse - " + fp); 230 var parsed = el.style.font; 231 el.style.font = kDefaultFontSetting; 232 el.style.font = parsed; 233 assert_equals(el.style.font, parsed, "font setter should parse serialized form to identical serialization - " + parsed + " ==> " + el.style.font); 234 } else { 235 assert_equals(el.style.font, def, "font setter shouldn't parse - " + fp); 236 } 237 } 238 239 var testFontVariations = [ 240 { size: "16px" }, 241 { size: "900px" }, 242 { size: "900em" }, 243 { size: "35%" }, 244 { size: "7832.3%" }, 245 { size: "xx-large" }, 246 { size: "larger", s1: "lighter" }, 247 { size: "16px", s1: "italic" }, 248 { size: "16px", s1: "italic", s2: "bold" }, 249 { size: "smaller", s1: "normal" }, 250 { size: "16px", s1: "normal", s2: "normal" }, 251 { size: "16px", s1: "400", s2: "normal" }, 252 { size: "16px", s1: "bolder", s2: "oblique" } 253 ]; 254 255 function testFamilyNameParsing() { 256 var i; 257 for (i = 0; i < testFontFamilyLists.length; i++) { 258 var tst = testFontFamilyLists[i]; 259 var n = tst.namelist; 260 var t; 261 262 if (!tst.fontonly) { 263 t = "font-family: " + n; 264 test(function() { testStyleRuleParse(t, tst.invalid); }, t); 265 test(function() { testFontFamilySetterParse(n, tst.invalid); }, t + " (setter)"); 266 } 267 268 var v; 269 for (v = 0; v < testFontVariations.length; v++) { 270 var f = testFontVariations[v]; 271 t = font(n, f.size, f.s1, f.s2); 272 test(function() { testStyleRuleParse(t, tst.invalid); }, t); 273 test(function() { testFontSetterParse(n, f.size, f.s1, f.s2, tst.invalid); }, t + " (setter)"); 274 } 275 } 276 } 277 278 testFamilyNameParsing(); 279 280 </script> 281 </body> 282 </html>