1 if(!dojo._hasResource["tests.number"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["tests.number"] = true;
3 dojo.provide("tests.number");
5 dojo.require("dojo.number");
8 * Refer to ICU4J's NumberFormatTest.expect(...)
10 tests.number.check=function(t,options,sourceInput,expectResult){
11 tests.number.checkFormatParseCycle(t, t,options,sourceInput,expectResult,false);
12 tests.number.checkParse(t, t,options,expectResult,sourceInput);
16 * Perform a single formatting check or a backward check
17 * backward check:number1 -(formatted)-> string1 -(parsed)-> number2 -(formated)-> string2
18 * then number should == number2; string1 should == string2
20 tests.number.checkFormatParseCycle=function(t,options,sourceInput,expectResult,
21 backwardCheck/*boolean,indicates whether need a backward chain check,like formate->parse->format*/){
23 var pattern = options.pattern;
24 var locale = options.locale;
25 //TODO: add more fields
29 var str = null==pattern?"default":pattern;
30 //print("pattern:" + str + "| locale:" + locale);
31 //print("input:" + sourceInput);
32 var result = dojo.number.format(sourceInput,options);
33 //print("result:" + result);
34 if(null != expectResult){
35 t.is(expectResult,result);
38 var resultParsed = dojo.number.parse(result,options);
39 //print("resultParsed:" + resultParsed);
40 if(!tests.number._decimalNumberDiff(sourceInput,resultParsed)){
41 t.is(sourceInput,resultParsed);
43 var resultParsedReformatted = dojo.number.format(resultParsed,options);
44 //print("resultParsedReformatted:" + resultParsedReformatted);
45 if(!tests.number._decimalNumberDiff(result,resultParsedReformatted)){
46 t.is(result,resultParsedReformatted);
52 * Perform a single parsing check
54 tests.number.checkParse=function(t,options,sourceInput,expectResult){
56 if(null != options && null != options.pattern){
57 str = options.pattern;
59 //print("input:" + sourceInput);
60 var result = dojo.number.parse(sourceInput,options);
61 //print("result :" + result);
62 if(null != expectResult){
63 t.is(expectResult,result);
68 * //TODO:Round a given number
70 tests.number.rounding = function(t,number,maxFractionDigits,expected){
72 for(var i=0; i<maxFractionDigits; i++){pattern += "#";}
73 var result = dojo.number.format(number,{pattern:pattern});
74 t.is(expected,result);
80 function runBatchParse(options,dataArray/*array*/,pass/*boolean*/){
84 var str = (null==options.pattern)?"default":options.pattern;
87 for(; i<dataArray.length; i++){
89 //print("["+i+"]"+"input:"+dataArray[i]);
90 result = dojo.number.parse(dataArray[i],options);
92 throw "\"" + dataArray[i] + "\" is parsed to NaN with pattern " + str;
94 //print("["+i+"]"+"output:"+result);
101 if(!pass && (exception == null)) {
102 throw "runBatchParse() - stric parse failed, no exception when parsing illegal data";
103 }else if(exception != null){
105 //strict parsing should fail for all the dataArray elements as expected
106 //pass condition for strict parsing
109 throw "runBatchParse() failed: " + exception;
114 * Check whether the given two numbers differ under the decimal bound
117 tests.number._decimalNumberDiff = function(num1,num2){
118 //TODO: should be more accurate when dojo.number finish rounding in the future
119 var diffBound = 1e-3;
120 var diff = num1 - num2;
121 //print("Math.abs(diff) " + Math.abs(diff));
122 if(Math.abs(diff) < diffBound ){
124 }else if(isNaN(Math.abs(diff))){
125 var s = num1.toString().split(num2);
126 s[1] = s[1].replace(",","0");
127 s[1] = s[1].replace('\u066b','0');
128 return (new Number(s[1])< diffBound);
133 tests.register("tests.number",
136 // Test formatting and parsing of currencies in various locales pre-built in dojo.cldr
137 // NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
138 // load resources here for specific locales:
142 var partLocaleList = ["en-us", "fr-fr", "de-de"];
144 for(var i = 0 ; i < partLocaleList.length; i ++){
145 dojo.requireLocalization("dojo.cldr","number",partLocaleList[i], "zh-cn,zh,ko-kr,pt,en-us,en-gb,de,ja,ja-jp,en,ROOT,en-au,fr,es,ko,zh-tw,it,es-es,de-de");
148 runTest: function(t){
152 name: "format", // old tests
153 runTest: function(t){
155 t.is("0123", dojo.number.format(123, {pattern: "0000"}));
156 t.is("-12,34,567.890", dojo.number.format(-1234567.89, {pattern: "#,##,##0.000##"}));
157 t.is("-12,34,567.89012", dojo.number.format(-1234567.890123, {pattern: "#,##,##0.000##"}));
158 t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#,##0.000##)"}));
159 t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#)"}));
160 t.is("50.1%", dojo.number.format(0.501, {pattern: "#0.#%"}));
161 t.is("98", dojo.number.format(1998, {pattern: "00"}));
162 t.is("01998", dojo.number.format(1998, {pattern: "00000"}));
163 t.is("0.13", dojo.number.format(0.125, {pattern: "0.##"})); //NOTE: expects round_half_up, not round_half_even
164 t.is("0.1250", dojo.number.format(0.125, {pattern: "0.0000"}));
165 t.is("0.1", dojo.number.format(0.100004, {pattern: "0.####"}));
167 t.is("-12", dojo.number.format(-12.3, {places:0, locale: "en-us"}));
168 t.is("-1,234,567.89", dojo.number.format(-1234567.89, {locale: "en-us"}));
169 // t.is("-12,34,567.89", dojo.number.format(-1234567.89, {locale: "en-in"}));
170 t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
171 // t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
172 t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
173 t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
174 t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
175 t.is("-1.234,56", dojo.number.format(-1234.56, {places:2, locale: "de-de"}));
176 t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
177 t.is("123.46%", dojo.number.format(1.23456, {places:2, locale: "en-us", type: "percent"}));
180 t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
181 // t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
182 t.is("-1,000.11", dojo.number.format(-1000.114, {places:2, locale: "en-us"}));
183 t.is("-1,000.11", dojo.number.format(-1000.115, {places:2, locale: "en-us"}));
184 t.is("-1,000.12", dojo.number.format(-1000.116, {places:2, locale: "en-us"}));
185 t.is("-0.00", dojo.number.format(-0.0001, {places:2, locale: "en-us"}));
186 t.is("0.00", dojo.number.format(0, {places:2, locale: "en-us"}));
188 //change decimal places
189 t.is("-1\xa0000,100", dojo.number.format(-1000.1, {places:3, locale: "fr-fr"}));
190 t.is("-1,000.100", dojo.number.format(-1000.1, {places:3, locale: "en-us"}));
194 name: "parse", // old tests
195 runTest: function(t){
196 t.is(1000, dojo.number.parse("1000", {locale: "en-us"}));
197 t.is(1000.123, dojo.number.parse("1000.123", {locale: "en-us"}));
198 t.is(1000, dojo.number.parse("1,000", {locale: "en-us"}));
199 t.is(-1000, dojo.number.parse("-1000", {locale: "en-us"}));
200 t.is(-1000.123, dojo.number.parse("-1000.123", {locale: "en-us"}));
201 t.is(-1234567.89, dojo.number.parse("-1,234,567.89", {locale: "en-us"}));
202 t.is(-1234567.89, dojo.number.parse("-1 234 567,89", {locale: "fr-fr"}));
203 t.t(isNaN(dojo.number.parse("-1 234 567,89", {locale: "en-us"})));
205 t.t(isNaN(dojo.number.parse("10,00", {locale: "en-us"})));
206 t.t(isNaN(dojo.number.parse("1000.1", {locale: "fr-fr"})));
208 t.t(isNaN(dojo.number.parse("")));
209 t.t(isNaN(dojo.number.parse("abcd")));
212 // t.is(-1234567, dojo.number.parse(" -1,234,567 ", {locale: "en-us"}));
214 // t.t(dojo.number.parse("9.1093826E-31"));
215 t.is(0.501, dojo.number.parse("50.1%", {pattern: "#0.#%"}));
217 t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#"}));
218 t.is(-123.4, dojo.number.parse("-123.4", {pattern: "#0.#"}));
219 t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#;(#0.#)"}));
220 t.is(-123.4, dojo.number.parse("(123.4)", {pattern: "#0.#;(#0.#)"}));
222 t.is(null, dojo.number.format("abcd", {pattern: "0000"}));
224 t.is(123, dojo.number.parse("123", {places:0}));
225 t.is(123, dojo.number.parse("123", {places:'0'}));
226 t.is(123.4, dojo.number.parse("123.4", {places:1}));
227 t.is(123.45, dojo.number.parse("123.45", {places:'1,3'}));
228 t.is(123.45, dojo.number.parse("123.45", {places:'0,2'}));
232 name: "format_icu4j3_6",
233 runTest: function(t){
235 /*************************************************************************************************
236 * Evan:The following test cases are referred from ICU4J 3.6 (NumberFormatTest etc.)
237 * see http://icu.sourceforge.net/download/3.6.html#ICU4J
238 *************************************************************************************************/
242 * In ICU4J, testing logic for NumberFormat.format() is seperated into
243 * differernt single tese cases. So part of these logic are
244 * collected together in this single method.
246 * !!Failed cases are as follows:
247 * 1.1234567890987654321234567890987654321 should be formatted as
248 * 1,234,567,890,987,654,321,234,567,890,987,654,321 with all the default parameters,
249 * but got 1.234 instead, may due to the unimplemeted exponent.
250 * 2.\u00a4 and ' are not replaced
251 * with pattern "'*&'' '\u00a4' ''&*' #,##0.00"
252 * 1.0 should be formatted to "*&' Re. '&* 1.00",but got "'*&'' '\u00a4' ''&*' 1.00" instead
256 //print("test_number_format_icu4j3_6() start..............");
257 /* !!Failed case, 1.234 returned instead
258 //refer to ICU4J's NumberFormatTest.TestCoverage()
259 var bigNum = 1234567890987654321234567890987654321;
260 var expectResult = "1,234,567,890,987,654,321,234,567,890,987,654,321";
261 tests.number.checkFormatParseCycle(t, null,bigNum,expectResult,false);
264 //in icu4j should throw out an exception when formatting a string,
265 //but it seems dojo.number.format can deal with strings
267 dojo.number.format("123456789");
269 //!!Failed case, \u00a4 and ' are not replaced
271 var options = {pattern:"'*&'' '\u00a4' ''&*' #,##0.00",locale:"en-us"};
272 tests.number.check(t, options,1.0, "*&' Re. '&* 1.00");
273 tests.number.check(t, options,-2.0, "-*&' Rs. '&* 2.00");
275 options = {pattern:"#,##0.00 '*&'' '\u00a4' ''&*'",locale:"en-us"};
276 tests.number.check(t, options,1.0,"1.00 *&' Re. '&*");
277 tests.number.check(t, options,-2.0,"-2.00 *&' Rs. '&*");
279 //print("test_number_format_icu4j3_6() end..............\n");
283 name: "format_patterns",
284 runTest: function(t){
287 * Refer to ICU4J's NumberFormatTest.TestPatterns() which now only coveres us locale
289 //print("test_number_format_Patterns() start..............");
290 var patterns = (["#0.#", "#0.", "#.0", "#"]);
291 var patternsLength = patterns.length;
292 var num = (["0","0", "0.0", "0"]);
294 //icu4j result seems doesn't work as:
295 //var num = (["0","0.", ".0", "0"]);
296 for (var i=0; i<patternsLength; ++i)
298 options = {pattern:patterns[i]};
299 tests.number.checkFormatParseCycle(t, options,0,num[i],false);
304 // unquoted special characters in the suffix are illegal
305 // so "000.000|###" is illegal; "000.000'|###'" is legal
306 //dojo.number.format:
307 // when formatting 1.2 with illegal pattern "000.000|###"
308 // no exception was thrown but got "001.200|###" instead.
311 patterns = (["000.000|###","000.000'|###'"]);
312 var exception = false;
314 for(var i = 0; i < patterns.length; i ++){
316 //"001.200'|###'" is return for "000.000'|###'"
317 //"001.200|###" is return for "000.000|###"
318 result = dojo.number.format(1.2,{pattern:patterns[i]});
319 print("["+i+"] 1.2 is formatted to " + result + " with pattern " + patterns[i]);
323 if(exception && i==1){
324 throw "["+i+"]Failed when formatting 1.2 using legal pattern " + patterns[i];
325 }else if(!exception && i==0){
326 throw "["+i+"]Failed when formatting 1.2 using illegal pattern " + patterns[i];
329 //print("test_number_format_Patterns() end..............\n");
334 runTest: function(t){
336 * TODO: For dojo.number future version
337 * Refer to ICU4J's NumberFormatTest.TestExponential()
342 name: "format_quotes",
343 runTest: function(t){
346 * Refer to ICU4J's NumberFormatTest.TestQuotes()
348 //print("test_number_format_Quotes() start..............");
349 //TODO: add more locales
352 //Pattern "s'aa''s'c#" should format 6666 to "saa'sc6666", but got s'aa''s'c6666 instead
353 // is this case necessary?
355 var pattern = "s'aa''s'c#";
356 var result = dojo.number.format(6666,{pattern:pattern,locale:"en-us"});
357 var expectResult = "saa'sc6666";
358 t.is(expectResult,result);
360 //print("test_number_format_Quotes() end..............");
364 name: "format_rounding",
365 runTest: function(t){
367 * Refer to ICU4J's NumberFormatTest.TestRounding487() and NumberFormatTest.TestRounding()
369 //print("test_number_format_rounding() start..............");
370 tests.number.rounding(t,0.000179999, 5, "0.00018");
371 tests.number.rounding(t,0.00099, 4, "0.001");
372 tests.number.rounding(t,17.6995, 3, "17.7");
373 tests.number.rounding(t,15.3999, 0, "15");
374 tests.number.rounding(t,-29.6, 0, "-30");
376 //TODO refer to NumberFormatTest.TestRounding()
378 //print("test_number_format_rounding() end..............");
382 name: "format_scientific",
383 runTest: function(t){
385 * TODO: For dojo.number future version
386 * Refer to ICU4J's NumberFormatTest.TestScientific()- Exponential testing
387 * Refer to ICU4J's NumberFormatTest.TestScientific2()
388 * Refer to ICU4J's NumberFormatTest.TestScientificGrouping()
393 name: "format_perMill",
394 runTest: function(t){
397 * Refer to ICU4J's NumberFormatTest.TestPerMill()
399 //print("test_number_format_PerMill() start..............");
404 //TODO: !!Failed case - ###.###\u2030(\u2030 is ‰)
405 //Pattern ###.###\u2030 should format 0.4857 as 485.7\u2030,but got 485.700\u2030 instead
406 pattern = "###.###\u2030";
407 expectResult = "485.7\u2030";
408 result = dojo.number.format(0.4857,{pattern:pattern});
409 t.is(expectResult,result);
411 //TODO: !!Failed mile percent case - ###.###m
412 //Pattern "###.###m" should format 0.4857 to 485.7m, but got 0.485m instead
414 pattern = "###.###m";
415 expectResult = "485.7m";
416 result = dojo.number.format(0.4857,{pattern:pattern,locale:"en"});
417 t.is(expectResult,result);
419 //print("test_number_format_PerMill() end..............\n");
423 name: "format_grouping",
424 runTest: function(t){
426 * Only test en-us and en-in
427 * Refer to ICU4J's NumberFormatTest.TestSecondaryGrouping()
429 //print("test_number_format_Grouping() start..............");
431 var sourceInput = 123456789;
432 var expectResult = "12,34,56,789";
433 var options = {pattern:"#,##,###",locale:"en-us"};
435 //step1: 123456789 formated=> 12,34,56,789
436 //step2:12,34,56,789 parsed=> 123456789 => formated => 12,34,56,789
437 tests.number.checkFormatParseCycle(t, options,sourceInput,expectResult,true);
439 //TODO: sencondary grouping not implemented yet ?
440 //Pattern "#,###" and secondaryGroupingSize=4 should format 123456789 to "12,3456,789"
442 //Special case for "en-in" locale
443 //1876543210 should be formated as 1,87,65,43,210 in "en-in" (India)
445 sourceInput = 1876543210;
446 expectResult = "1,87,65,43,210";
447 var result = dojo.number.format(sourceInput,{locale:"en-in"});
448 t.is(expectResult,result);
450 //print("test_number_format_Grouping() end..............\n");
455 runTest: function(t){
457 * TODO:!!Failed cases:
458 * According to ICU4J test criteria:
459 * 1.with pattern "*^##.##":
460 * 0 should be formatted to "^^^^0",but got "*^0" instead,
461 * -1.3 should be formatted to "^-1.3",but got "-*^1.3" instead.
463 * 2.with pattern "##0.0####*_ 'g-m/s^2'" :
464 * 0 should be formatted to "0.0______ g-m/s^2",but got ":0.0*_ 'g-m/s^2'" instead
465 * 1.0/3 should be formatted to "0.33333__ g-m/s^2",but got "0.33333*_ 'g-m/s^2'" instead
467 * 3.with pattern "*x#,###,###,##0.0#;*x(###,###,##0.0#)":
468 * -10 should be formatted to "xxxxxxxxxx(10.0)",but got "*x(10.0)" instead.
469 * 10 should be formatted to "xxxxxxxxxxxx10.0",but got "*x10.0" instead.
471 * -1120456.37 should be formatted to "xx(1,120,456.37)",but got "*x(1,120,456.37)" instead.
472 * 1120456.37 should be formatted to "xxxx1,120,456.37",but got "*x1,120,456.37" instead.
473 * -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "*x(1,252,045,600.37)" instead.
474 * 1252045600.37 should be formatted to "10,252,045,600.37",but got "*x10,252,045,600.37" instead.
476 * 4.with pattern "#,###,###,##0.0#*x;(###,###,##0.0#*x)"
477 * -10 should be formatted to (10.0xxxxxxxxxx),but got "(10.0*x)" instead.
478 * 10 should be formatted to "10.0xxxxxxxxxxxx",but got "10.0*x" instead.
480 * -1120456.37 should be formatted to "(1,120,456.37xx)",but got "(1,120,456.37*x)" instead.
481 * 1120456.37 should be formatted to "xxxx1,120,456.37",but got "1,120,456.37*x" instead.
482 * -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "(1,252,045,600.37*x)" instead.
483 * 1252045600.37 should be formatted to ""10,252,045,600.37"",but got "10,252,045,600.37*x" instead.*
485 * Refer to ICU4J's NumberFormatTest.TestPad()
488 function test_number_format_pad(){
489 var locale = "en-us";
490 print("test_number_format_Pad() start..............");
491 var options = {pattern:"*^##.##",locale:locale};
493 tests.number.check(t, options,0,"^^^^0");
494 tests.number.check(t, options,-1.3,"^-1.3");
497 options = {pattern:"##0.0####*_ 'g-m/s^2'",locale:locale};
498 tests.number.check(t, options,0,"0.0______ g-m/s^2");
499 tests.number.checkFormatParseCycle(t, options,1.0/3,"0.33333__ g-m/s^2",true);
501 //exponent not implemented
502 //options = {pattern:"##0.0####E0*_ 'g-m/s^2'",locale:locale};
503 //tests.number.check(t, options,0,"0.0E0______ g-m/s^2");
504 //tests.number.checkFormatParseCycle(t, options,1.0/3,"333.333E-3_ g-m/s^2",true);
506 // Test padding before a sign
507 options = {pattern:"*x#,###,###,##0.0#;*x(###,###,##0.0#)",locale:locale};
509 tests.number.check(t, options,-10,"xxxxxxxxxx(10.0)");
510 tests.number.check(t, options,-1000, "xxxxxxx(1,000.0)");
511 tests.number.check(t, options,-1000000, "xxx(1,000,000.0)");
512 tests.number.check(t, options,-100.37, "xxxxxxxx(100.37)");
513 tests.number.check(t, options,-10456.37, "xxxxx(10,456.37)");
514 tests.number.check(t, options,-1120456.37, "xx(1,120,456.37)");
515 tests.number.check(t, options,-112045600.37, "(112,045,600.37)");
516 tests.number.check(t, options,-1252045600.37, "(1,252,045,600.37)");
519 tests.number.check(t, options,10, "xxxxxxxxxxxx10.0");
520 tests.number.check(t, options,1000, "xxxxxxxxx1,000.0");
521 tests.number.check(t, options,1000000, "xxxxx1,000,000.0");
522 tests.number.check(t, options,100.37, "xxxxxxxxxx100.37");
523 tests.number.check(t, options,10456.37, "xxxxxxx10,456.37");
524 tests.number.check(t, options,1120456.37, "xxxx1,120,456.37");
525 tests.number.check(t, options,112045600.37, "xx112,045,600.37");
526 tests.number.check(t, options,10252045600.37, "10,252,045,600.37");
528 // Test padding between a sign and a number
529 options = {pattern:"#,###,###,##0.0#*x;(###,###,##0.0#*x)",locale:locale};
530 tests.number.check(t, options, -10, "(10.0xxxxxxxxxx)");
531 tests.number.check(t, options, -1000, "(1,000.0xxxxxxx)");
532 tests.number.check(t, options, -1000000, "(1,000,000.0xxx)");
533 tests.number.check(t, options, -100.37, "(100.37xxxxxxxx)");
534 tests.number.check(t, options, -10456.37, "(10,456.37xxxxx)");
535 tests.number.check(t, options, -1120456.37, "(1,120,456.37xx)");
536 tests.number.check(t, options, -112045600.37, "(112,045,600.37)");
537 tests.number.check(t, options, -1252045600.37, "(1,252,045,600.37)");
539 tests.number.check(t, options, 10, "10.0xxxxxxxxxxxx");
540 tests.number.check(t, options, 1000, "1,000.0xxxxxxxxx");
541 tests.number.check(t, options, 1000000, "1,000,000.0xxxxx");
542 tests.number.check(t, options, 100.37, "100.37xxxxxxxxxx");
543 tests.number.check(t, options, 10456.37, "10,456.37xxxxxxx");
544 tests.number.check(t, options, 1120456.37, "1,120,456.37xxxx");
545 tests.number.check(t, options, 112045600.37, "112,045,600.37xx");
546 tests.number.check(t, options, 10252045600.37, "10,252,045,600.37");
548 //Not implemented yet,refer to NumberFormatTest.TestPatterns2()
549 //For future use - maily test pad patterns
550 print("test_number_format_Pad() end..............");
556 name: "parse_icu4j3_6",
557 runTest: function(t){
559 * In ICU4J, testing logic for NumberFormat.parse() is seperated into
560 * differernt single tese cases. So part of these logic are
561 * collected together in this test case. *
563 //print("test_number_parse_icu4j3_6() start..............");
564 //Refer to ICU4J's NumberFormatTest.TestParse() which is only a rudimentary version
567 var result = dojo.number.parse(str,{pattern:pattern});
568 //TODO: add more locales
569 //FIXME: is this a valid test?
572 /**************************************** tolerant parse *****************************************
573 * refers to ICU4J's NumberFormatTest.TestStrictParse()??
574 * TODO: Seems dojo.number parses string in a tolerant way.
576 var options = {locale:"en-us"};
578 * TODO: !!Failed case,Should all pass,
579 * but the following elements failed (all parsed to NaN):
580 * [1]-"0 ",[2]-"0.",[3]-"0,",[5]-"0. ",[6]-"0.100,5",
581 * [7]-".00",[9]-"12345, ",[10]-"1,234, ",[12]-"0E"
584 "0", //[0] single zero before end of text is not leading
585 //"0 ", //[1] single zero at end of number is not leading
586 //"0.", //[2] single zero before period (or decimal, it's ambiguous) is not leading
587 //"0,", //[3] single zero before comma (not group separator) is not leading
588 "0.0", //[4] single zero before decimal followed by digit is not leading
589 //"0. ", //[5] same as above before period (or decimal) is not leading
590 //"0.100,5", //[6] comma stops parse of decimal (no grouping)
591 //".00", //[7] leading decimal is ok, even with zeros
592 "1234567", //[8] group separators are not required
593 //"12345, ", //[9] comma not followed by digit is not a group separator, but end of number
594 //"1,234, ", //[10] if group separator is present, group sizes must be appropriate
595 "1,234,567" //[11] ...secondary too
596 //,"0E" //[12]not implemented yet,an exponnent not followed by zero or digits is not an exponent
598 runBatchParse(options,passData,true/*tolerant parse*/);
601 * TODO:!!Failed case,should all pass,
602 * but the following failed,
603 * [10]-"1,45 that" implies that we partially parse input
606 "00", //[0] leading zero before zero
607 "012", //[1] leading zero before digit
608 "0,456", //[2] leading zero before group separator
609 "1,2", //[3] wrong number of digits after group separator
610 ",0", //[4] leading group separator before zero
611 ",1", //[5] leading group separator before digit
612 ",.02", //[6] leading group separator before decimal
613 "1,.02", //[7] group separator before decimal
614 "1,,200", //[8] multiple group separators
615 "1,45", //[9] wrong number of digits in primary group
616 //"1,45 that", //[10] wrong number of digits in primary group
617 "1,45.34", //[11] wrong number of digits in primary group
618 "1234,567", //[12] wrong number of digits in secondary group
619 "12,34,567", //[13] wrong number of digits in secondary group
620 "1,23,456,7890" //[14] wrong number of digits in primary and secondary groups
622 runBatchParse(options,failData,false);
624 options = {pattern:"#,##,##0.#",locale:"en-us"};
626 * TODO:!!Failed case,shoudl all pass.
628 * but [1] [2] and [3] failed
629 * should be parsed to 1234567,but NaN instead
631 var mixedPassData = ([
633 //,"12,34,567," //[1]
634 //"12,34,567, that",//[2]
635 //"12,34,567 that" //[3]
637 runBatchParse(options,mixedPassData,true/*tolerant parse*/);
640 * TODO:!!Failed case,should all pass,
641 * but actually mixedFailData[2] and mixedFailData[3] passed.
642 * "12,34,56, that " and [3]-"12,34,56 that" should be parsed to 123456,but NaN instead
644 var mixedFailData = ([
647 //,"12,34,56, that ",//[2]
648 //"12,34,56 that", //[3]
650 runBatchParse(options,mixedFailData,false);
653 /**************************************** strict parse ******************************************
654 * TODO:May need to test strict parsing in the future?
655 * e.g. A strict parsing like (with pattern "#,##0.#")
657 * '00', '0123' fail the parse, but '0' and '0.001' pass
658 * 2.Leading or doubled grouping separators
659 * ',123' and '1,,234" fail
660 * 3.Groups of incorrect length when grouping is used
661 * '1,23' and '1234,567' fail, but '1234' passes
662 * 4.Grouping separators used in numbers followed by exponents
663 * '1,234E5' fails, but '1234E5' and '1,234E' pass
665 //options={locale:"en",strict:true};
666 //runBatchParse(options,passData,false/*strict parse*/);
667 //runBatchParse(options,failData,false/*strict parse*/);
669 //options = {pattern:"#,##,##0.#",locale:"en-us",strict:true};
670 //runBatchParse(options,mixedPassData,false/*strict parse*/);
671 //runBatchParse(options,mixedFailData,false/*strict parse*/);
673 //print("test_number_parse_icu4j3_6() end..............\n");
677 name: "parse_whitespace",
678 runTest: function(t){
681 * With pattern "a b#0c ",both "a b3456c " and and "a b1234c " should be parsed to 3456,but got NaN instead.
683 * Refer to ICU4J's NumberFormatTest.TestWhiteSpaceParsing
686 print("test_number_parse_WhiteSpace() start..............");
687 var pattern = "a b#0c ";
688 var expectResult = 3456;
689 result = dojo.number.parse("a b3456c ",{pattern:pattern,locale:"en-us"});
690 t.is(expectResult,result);
691 result = dojo.number.parse("a b3456c ",{pattern:pattern,locale:"en-us"});
692 t.is(expectResult,result);
693 print("test_number_parse_WhiteSpace() end..............\n");
697 /*************************************************************************************************
698 * Regression test cases
699 * These test cases are referred to ICU4J's NumberFormatRegressionTest and NumberFormatRegression.
700 * The regression cases in ICU4J are used as unit test cases for bug fixing,
701 * They are inluced here so that dojo.number may avoid those similar bugs.
702 *************************************************************************************************/
704 name: "number_regression_1",
705 runTest: function(t){
707 * Refer to ICU4J's NumberFormatRegressionTest.Test4161100()
709 tests.number.checkFormatParseCycle(t, {pattern:"#0.#"},-0.09,"-0.1",false);
713 name: "number_regression_2",
714 runTest: function(t){
716 * !!Failed case,rounding hasn't been implemented yet.
717 * Refer to ICU4J's NumberFormatRegressionTest.Test4408066()
720 var data = ([-3.75, -2.5, -1.5,
724 var expected = (["-4", "-2", "-2",
728 var options = {locale:"zh-cn",round:true};
729 for(var i =0; i < data.length; i++){
730 tests.number.checkFormatParseCycle(t, options,data[i],expected[i],false);
733 data = ([ "-3.75", "-2.5", "-1.5",
735 "1.25", "1.5", "2.5",
736 "3.75", "10.0", "255.5"]);
737 expected =([ -3, -2, -1,
742 for(var i =0; i < data.length; i++){
743 tests.number.checkParse(t, options,data[i],expected[i]);
749 name: "number_regression_3",
750 runTest: function(t){
752 * Refer to ICU4J's NumberRegression.Test4087535() and Test4243108()
754 tests.number.checkFormatParseCycle(t, {places:0},0,"0",false);
755 //TODO:in icu4j,0.1 should be formatted to ".1" when minimumIntegerDigits=0
756 tests.number.checkFormatParseCycle(t, {places:0},0.1,"0",false);
757 tests.number.checkParse(t, {pattern:"#0.#####"},123.55456,123.55456);
758 //!! fails because default pattern only has 3 decimal places
759 // tests.number.checkParse(t, null,123.55456,123.55456);
761 //See whether it fails first format 0.0 ,parse "99.99",and then reformat 0.0
762 tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
763 tests.number.checkParse(t, null,"99.99",99.99);
764 tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
768 name: "number_regression_4",
769 runTest: function(t){
772 * In ICU -0.0 and -0.0001 should be formatted to "-0" with FieldPosition(0)
773 * dojo.i18n.number format -0.0 to "-0"; -0.0001 to "-0.000100"
775 * Refer to ICU4J's NumberRegression.Test4088503() and Test4106658()
777 tests.number.checkFormatParseCycle(t, {places:0},123,"123",false);
779 //TODO: differernt from ICU where -0.0 is formatted to "-0"
780 tests.number.checkFormatParseCycle(t, {locale:"en-us"},-0.0,"0",false);
782 //TODO: differernt from ICU where -0.0001 is formatted to "-0"
783 tests.number.checkFormatParseCycle(t, {locale:"en-us",places:6},-0.0001,"-0.000100",false);
787 name: "number_regression_5",
788 runTest: function(t){
790 * !!Failed case,rounding has not implemented yet.
791 * 0.00159999 should be formatted as 0.0016 but got 0.0015 instead.
792 * Refer to ICU4J's NumberRegression.Test4071492()
794 //tests.number.checkFormatParseCycle(t, {places:4,round:true},0.00159999,"0.0016",false);
798 name: "number_regression_6",
799 runTest: function(t){
801 * Refer to ICU4J's NumberRegression.Test4086575()
803 var pattern = "###.00;(###.00)";
805 var options = {pattern:pattern,locale:locale};
808 tests.number.checkFormatParseCycle(t, options,1234,"1234,00",false);
809 tests.number.checkFormatParseCycle(t, options,-1234,"(1234,00)",false);
811 //space as group separator
812 pattern = "#,###.00;(#,###.00)";
813 options = {pattern:pattern,locale:locale};
814 tests.number.checkFormatParseCycle(t, options,1234,"1\u00a0234,00",false);// Expect 1 234,00
815 tests.number.checkFormatParseCycle(t, options,-1234,"(1\u00a0234,00)",false); // Expect (1 234,00)
819 name: "number_regression_7",
820 runTest: function(t){
822 * !!Failed case - expontent has not implemented yet
823 * shuold format 1.000000000000001E7 to 10000000.00000001, but got 10,000,000.000 instead
824 * Refer to ICU4J's NumberRegression.Test4090489() - loses precision
826 //tests.number.checkFormatParseCycle(t, null,1.000000000000001E7,"10000000.00000001",false);
830 name: "number_regression_8",
831 runTest: function(t){
834 * 1.with pattern "#,#00.00 p''ieces;-#,#00.00 p''ieces"
835 * 3456.78 should be formated to "3,456.78 p'ieces",
836 * but got "3,456.78 p''ieces","''" should be replaced with "'"
837 * 2.with illegal pattern "000.0#0"
838 * no error for the illegal pattern, and 3456.78 is formatted to 456.780
839 * 3.with illegal pattern "0#0.000"
840 * no error for the illegal pattern, and 3456.78 is formatted to 3456.780
842 * Refer to ICU4J's NumberRegression.Test4092480(),Test4074454()
844 var patterns = (["#0000","#000","#00","#0","#"]);
845 var expect = (["0042","042","42","42","42"]);
847 for(var i =0; i < patterns.length; i ++){
848 tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},42,expect[i],false);
849 tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},-42,"-"+expect[i],false);
852 tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00;-#.#"},3456.78,"3,456.78",false);
854 //tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00 p''ieces;-#,#00.00 p''ieces"},3456.78,"3,456.78 p'ieces",false);
855 //tests.number.checkFormatParseCycle(t, {pattern:"000.0#0"},3456.78,null,false);
856 //tests.number.checkFormatParseCycle(t, {pattern:"0#0.000"},3456.78,null,false);
860 name: "number_regression_9",
861 runTest: function(t){
864 * Refer to ICU4J's NumberRegression.Test4052223()
866 //TODO:only got NaN,need an illegal pattern exception?
867 tests.number.checkParse(t, {pattern:"#,#00.00"},"abc3");
869 //TODO: got NaN instead of 1.222, is it ok?
870 //tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222,111",1.222);
871 //tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222x111",1.222);
873 //got NaN for illeal input,ok
874 tests.number.checkParse(t, null,"hello: ,.#$@^&**10x");
878 name: "number_regression_10",
879 runTest: function(t){
881 * Refer to ICU4J's NumberRegression.Test4125885()
883 tests.number.checkFormatParseCycle(t, {pattern:"000.00"},12.34,"012.34",false);
884 tests.number.checkFormatParseCycle(t, {pattern:"+000.00%;-000.00%"},0.1234,"+012.34%",false);
885 tests.number.checkFormatParseCycle(t, {pattern:"##,###,###.00"},9.02,"9.02",false);
887 var patterns =(["#.00", "0.00", "00.00", "#0.0#", "#0.00"]);
888 var expect = (["1.20", "1.20", "01.20", "1.2", "1.20" ]);
889 for(var i =0 ; i < patterns.length; i ++){
890 tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},1.2,expect[i],false);
895 name: "number_regression_11",
896 runTest: function(t){
899 * Make sure that all special characters, when quoted in a suffix or prefix, lose their special meaning.
900 * The detail error info :
902 * pattern:'0'#0'0'; expect:"01230"; but got "'3'#0'0'" instead
903 * pattern:','#0','; expect:",123,"; but got "','123','" instead
904 * pattern:'.'#0'.'; expect:".123."; but got "'.'123'.'" instead
905 * pattern:'‰'#0'‰'; expect:"‰123‰"; but got "'‰'123000'‰'" instead
906 * pattern:'%'#0'%'; expect:"%123%"; but got "'%'12300'%'" instead
907 * pattern:'#'#0'#'; expect:"#123#"; but got "'123'#0'#'" instead
908 * pattern:';'#0';'; expect:";123;"; but got "[dojo-test] FATAL exception raised:
909 * unable to find a number expression in pattern: '"
910 * pattern:'E'#0'E'; expect:"E123E"; not implemeted yet
911 * pattern:'*'#0'*'; expect:"*123*"; but got "'*'123'*'" instead
912 * pattern:'+'#0'+'; expect:"+123+"; but got "'+'123'+'" instead
913 * pattern:'-'#0'-'; expect:"-123-"; but got "'-'123'-'" instead
915 * TODO: is it ok to remain "'" in the formatted result as above??
917 * Refer to ICU4J's NumberRegression.Test4212072()
920 var specials = ([ '0', ',', '.', '\u2030', '%', '#',';', 'E', '*', '+', '-']);
924 for(var i=0; i < specials.length; i ++){
925 pattern = "'" + specials[i] + "'#0'" + specials[i] + "'";
926 expect = "" + specials[i] + "123" + specials[i];
927 tests.number.checkFormatParseCycle(t, {pattern:pattern,locale:"en-us"},123,expect,false);
933 name: "number_regression_12",
934 runTest: function(t){
936 * TODO: add more rounding test cases, refer to ICU4J's NumberRegression.Test4071005(),Test4071014() etc..
940 * TODO:Decimal format doesnt round a double properly when the number is less than 1
942 * Refer to ICU4J's NumberRegression.test4241880()
945 var input = ([ .019, .009, .015, .016, .014,
946 .004, .005, .006, .007, .008,
947 .5, 1.5, .05, .15, .005,
948 .015, .0005, .0015]);
949 var patterns = (["##0%", "##0%", "##0%", "##0%", "##0%",
950 "##0%", "##0%", "##0%", "##0%", "##0%",
951 "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
952 "#,##0.00", "#,##0.000", "#,##0.000"]);
953 var expect =([ "2%", "1%", "2%", "2%", "1%",
954 "0%", "0%", "1%", "1%", "1%",
955 "0", "2", "0.0", "0.2", "0.00",
956 "0.02", "0.000", "0.002",]);
957 for(var i = 0; i <input.length; i ++){
958 tests.number.checkFormatParseCycle(t, {pattern:patterns[i],round:true},input[i],expect[i],false);