toolkit/devtools/pretty-fast/tests/unit/test.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:5294ac518f2a
1 /*
2 * Copyright 2013 Mozilla Foundation and contributors
3 * Licensed under the New BSD license. See LICENSE.md or:
4 * http://opensource.org/licenses/BSD-2-Clause
5 */
6 var prettyFast = this.prettyFast || require("./pretty-fast");
7
8 var testCases = [
9
10 {
11 name: "Simple function",
12 input: "function foo() { bar(); }",
13 output: "function foo() {\n" +
14 " bar();\n" +
15 "}\n",
16 mappings: [
17 // function foo() {
18 {
19 inputLine: 1,
20 outputLine: 1
21 },
22 // bar();
23 {
24 inputLine: 1,
25 outputLine: 2
26 },
27 // }
28 {
29 inputLine: 1,
30 outputLine: 3
31 },
32 ]
33 },
34
35 {
36 name: "Nested function",
37 input: "function foo() { function bar() { debugger; } bar(); }",
38 output: "function foo() {\n" +
39 " function bar() {\n" +
40 " debugger;\n" +
41 " }\n" +
42 " bar();\n" +
43 "}\n",
44 mappings: [
45 // function bar() {
46 {
47 inputLine: 1,
48 outputLine: 2
49 },
50 // debugger;
51 {
52 inputLine: 1,
53 outputLine: 3
54 },
55 // bar();
56 {
57 inputLine: 1,
58 outputLine: 5
59 },
60 ]
61 },
62
63 {
64 name: "Immediately invoked function expression",
65 input: "(function(){thingy()}())",
66 output: "(function () {\n" +
67 " thingy()\n" +
68 "}())\n"
69 },
70
71 {
72 name: "Single line comment",
73 input: "// Comment\n" +
74 "function foo() { bar(); }\n",
75 output: "// Comment\n" +
76 "function foo() {\n" +
77 " bar();\n" +
78 "}\n",
79 mappings: [
80 // // Comment
81 {
82 inputLine: 1,
83 outputLine: 1
84 }
85 ]
86 },
87
88 {
89 name: "Multi line comment",
90 input: "/* Comment\n" +
91 "more comment */\n" +
92 "function foo() { bar(); }\n",
93 output: "/* Comment\n" +
94 "more comment */\n" +
95 "function foo() {\n" +
96 " bar();\n" +
97 "}\n",
98 mappings: [
99 // /* Comment
100 {
101 inputLine: 1,
102 outputLine: 1
103 },
104 // \nmore comment */
105 {
106 inputLine: 1,
107 outputLine: 2
108 }
109 ]
110 },
111
112 {
113 name: "Null assignment",
114 input: "var i=null;\n",
115 output: "var i = null;\n",
116 mappings: [
117 {
118 inputLine: 1,
119 outputLine: 1
120 }
121 ]
122 },
123
124 {
125 name: "Undefined assignment",
126 input: "var i=undefined;\n",
127 output: "var i = undefined;\n"
128 },
129
130 {
131 name: "Void 0 assignment",
132 input: "var i=void 0;\n",
133 output: "var i = void 0;\n"
134 },
135
136 {
137 name: "This property access",
138 input: "var foo=this.foo;\n",
139 output: "var foo = this.foo;\n"
140 },
141
142 {
143 name: "True assignment",
144 input: "var foo=true;\n",
145 output: "var foo = true;\n"
146 },
147
148 {
149 name: "False assignment",
150 input: "var foo=false;\n",
151 output: "var foo = false;\n"
152 },
153
154 {
155 name: "For loop",
156 input: "for (var i = 0; i < n; i++) { console.log(i); }",
157 output: "for (var i = 0; i < n; i++) {\n" +
158 " console.log(i);\n" +
159 "}\n",
160 mappings: [
161 // for (var i = 0; i < n; i++) {
162 {
163 inputLine: 1,
164 outputLine: 1
165 },
166 // console.log(i);
167 {
168 inputLine: 1,
169 outputLine: 2
170 },
171 ]
172 },
173
174 {
175 name: "String with semicolon",
176 input: "var foo = ';';\n",
177 output: "var foo = ';';\n"
178 },
179
180 {
181 name: "String with quote",
182 input: "var foo = \"'\";\n",
183 output: "var foo = '\\'';\n"
184 },
185
186 {
187 name: "Function calls",
188 input: "var result=func(a,b,c,d);",
189 output: "var result = func(a, b, c, d);\n"
190 },
191
192 {
193 name: "Regexp",
194 input: "var r=/foobar/g;",
195 output: "var r = /foobar/g;\n"
196 },
197
198 {
199 name: "In operator",
200 input: "if(foo in bar){doThing()}",
201 output: "if (foo in bar) {\n" +
202 " doThing()\n" +
203 "}\n"
204 },
205
206 {
207 name: "With statement",
208 input: "with(obj){crock()}",
209 output: "with (obj) {\n" +
210 " crock()\n" +
211 "}\n"
212 },
213
214 {
215 name: "New expression",
216 input: "var foo=new Foo();",
217 output: "var foo = new Foo();\n"
218 },
219
220 {
221 name: "Continue/break statements",
222 input: "while(1){if(x){continue}if(y){break}if(z){break foo}}",
223 output: "while (1) {\n" +
224 " if (x) {\n" +
225 " continue\n" +
226 " }\n" +
227 " if (y) {\n" +
228 " break\n" +
229 " }\n" +
230 " if (z) {\n" +
231 " break foo\n" +
232 " }\n" +
233 "}\n"
234 },
235
236 {
237 name: "Instanceof",
238 input: "var a=x instanceof y;",
239 output: "var a = x instanceof y;\n"
240 },
241
242 {
243 name: "Binary operators",
244 input: "var a=5*30;var b=5>>3;",
245 output: "var a = 5 * 30;\n" +
246 "var b = 5 >> 3;\n"
247 },
248
249 {
250 name: "Delete",
251 input: "delete obj.prop;",
252 output: "delete obj.prop;\n"
253 },
254
255 {
256 name: "Try/catch/finally statement",
257 input: "try{dangerous()}catch(e){handle(e)}finally{cleanup()}",
258 output: "try {\n" +
259 " dangerous()\n" +
260 "} catch (e) {\n" +
261 " handle(e)\n" +
262 "} finally {\n" +
263 " cleanup()\n" +
264 "}\n"
265 },
266
267 {
268 name: "If/else statement",
269 input: "if(c){then()}else{other()}",
270 output: "if (c) {\n" +
271 " then()\n" +
272 "} else {\n" +
273 " other()\n" +
274 "}\n"
275 },
276
277 {
278 name: "If/else without curlies",
279 input: "if(c) a else b",
280 output: "if (c) a else b\n"
281 },
282
283 {
284 name: "Objects",
285 input: "var o={a:1,\n" +
286 " b:2};",
287 output: "var o = {\n" +
288 " a: 1,\n" +
289 " b: 2\n" +
290 "};\n",
291 mappings: [
292 // a: 1,
293 {
294 inputLine: 1,
295 outputLine: 2
296 },
297 // b: 2
298 {
299 inputLine: 2,
300 outputLine: 3
301 },
302 ]
303 },
304
305 {
306 name: "Do/while loop",
307 input: "do{x}while(y)",
308 output: "do {\n" +
309 " x\n" +
310 "} while (y)\n"
311 },
312
313 {
314 name: "Arrays",
315 input: "var a=[1,2,3];",
316 output: "var a = [\n" +
317 " 1,\n" +
318 " 2,\n" +
319 " 3\n" +
320 "];\n"
321 },
322
323 {
324 name: "Code that relies on ASI",
325 input: "var foo = 10\n" +
326 "var bar = 20\n" +
327 "function g() {\n" +
328 " a()\n" +
329 " b()\n" +
330 "}",
331 output: "var foo = 10\n" +
332 "var bar = 20\n" +
333 "function g() {\n" +
334 " a()\n" +
335 " b()\n" +
336 "}\n"
337 },
338
339 {
340 name: "Ternary operator",
341 input: "bar?baz:bang;",
342 output: "bar ? baz : bang;\n"
343 },
344
345 {
346 name: "Switch statements",
347 input: "switch(x){case a:foo();break;default:bar()}",
348 output: "switch (x) {\n" +
349 "case a:\n" +
350 " foo();\n" +
351 " break;\n" +
352 "default:\n" +
353 " bar()\n" +
354 "}\n"
355 },
356
357 {
358 name: "Multiple single line comments",
359 input: "function f() {\n" +
360 " // a\n" +
361 " // b\n" +
362 " // c\n" +
363 "}\n",
364 output: "function f() {\n" +
365 " // a\n" +
366 " // b\n" +
367 " // c\n" +
368 "}\n",
369 },
370
371 {
372 name: "Indented multiline comment",
373 input: "function foo() {\n" +
374 " /**\n" +
375 " * java doc style comment\n" +
376 " * more comment\n" +
377 " */\n" +
378 " bar();\n" +
379 "}\n",
380 output: "function foo() {\n" +
381 " /**\n" +
382 " * java doc style comment\n" +
383 " * more comment\n" +
384 " */\n" +
385 " bar();\n" +
386 "}\n",
387 },
388
389 {
390 name: "ASI return",
391 input: "function f() {\n" +
392 " return\n" +
393 " {}\n" +
394 "}\n",
395 output: "function f() {\n" +
396 " return\n" +
397 " {\n" +
398 " }\n" +
399 "}\n",
400 },
401
402 {
403 name: "Non-ASI property access",
404 input: "[1,2,3]\n" +
405 "[0]",
406 output: "[\n" +
407 " 1,\n" +
408 " 2,\n" +
409 " 3\n" +
410 "]\n" +
411 "[0]\n"
412 },
413
414 {
415 name: "Non-ASI in",
416 input: "'x'\n" +
417 "in foo",
418 output: "'x' in foo\n"
419 },
420
421 {
422 name: "Non-ASI function call",
423 input: "f\n" +
424 "()",
425 output: "f()\n"
426 },
427
428 {
429 name: "Non-ASI new",
430 input: "new\n" +
431 "F()",
432 output: "new F()\n"
433 },
434
435 {
436 name: "Getter and setter literals",
437 input: "var obj={get foo(){return this._foo},set foo(v){this._foo=v}}",
438 output: "var obj = {\n" +
439 " get foo() {\n" +
440 " return this._foo\n" +
441 " },\n" +
442 " set foo(v) {\n" +
443 " this._foo = v\n" +
444 " }\n" +
445 "}\n"
446 },
447
448 {
449 name: "Escaping backslashes in strings",
450 input: "'\\\\'\n",
451 output: "'\\\\'\n"
452 },
453
454 {
455 name: "Escaping carriage return in strings",
456 input: "'\\r'\n",
457 output: "'\\r'\n"
458 },
459
460 {
461 name: "Escaping tab in strings",
462 input: "'\\t'\n",
463 output: "'\\t'\n"
464 },
465
466 {
467 name: "Escaping vertical tab in strings",
468 input: "'\\v'\n",
469 output: "'\\v'\n"
470 },
471
472 {
473 name: "Escaping form feed in strings",
474 input: "'\\f'\n",
475 output: "'\\f'\n"
476 },
477
478 {
479 name: "Escaping null character in strings",
480 input: "'\\0'\n",
481 output: "'\\0'\n"
482 },
483
484 ];
485
486 var sourceMap = this.sourceMap || require("source-map");
487
488 function run_test() {
489 testCases.forEach(function (test) {
490 console.log(test.name);
491
492 var actual = prettyFast(test.input, {
493 indent: " ",
494 url: "test.js"
495 });
496
497 if (actual.code !== test.output) {
498 throw new Error("Expected:\n" + test.output
499 + "\nGot:\n" + actual.code);
500 }
501
502 if (test.mappings) {
503 var smc = new sourceMap.SourceMapConsumer(actual.map.toJSON());
504 test.mappings.forEach(function (m) {
505 var query = { line: m.outputLine, column: 0 };
506 var original = smc.originalPositionFor(query);
507 if (original.line != m.inputLine) {
508 throw new Error("Querying:\n" + JSON.stringify(query, null, 2) + "\n"
509 + "Expected line:\n" + m.inputLine + "\n"
510 + "Got:\n" + JSON.stringify(original, null, 2));
511 }
512 });
513 }
514 });
515 console.log("✓ All tests pass!");
516 }
517
518 // Only run the tests if this is node and we are running this file
519 // directly. (Firefox's test runner will import this test file, and then call
520 // run_test itself.)
521 if (typeof require == "function" && typeof module == "object"
522 && require.main === module) {
523 run_test();
524 }

mercurial