#!/usr/bin/env python # -*- coding: utf-8 -*- ''' {{&header_text}} The MIT License (MIT) Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' import re import unittest import jsbeautifier import six import copy class TestJSBeautifier(unittest.TestCase): options = None @classmethod def setUpClass(cls): true = True false = False default_options = jsbeautifier.default_options() default_options.indent_size = 4 default_options.indent_char = ' ' default_options.preserve_newlines = True default_options.jslint_happy = False default_options.keep_array_indentation = False default_options.brace_style = 'collapse' default_options.indent_level = 0 default_options.break_chained_methods = False default_options.eol = '\n' {{#default_options}} default_options.{{name}} = {{&value}} {{/default_options}} cls.default_options = default_options cls.wrapregex = re.compile('^(.+)$', re.MULTILINE) def reset_options(self): self.options = copy.copy(self.default_options) def test_unescape(self): # Test cases contributed by test_fragment = self.decodesto self.reset_options() bt = self.bt def unicode_char(value): return six.unichr(value) bt('"\\\\s"') # == "\\s" in the js source bt("'\\\\s'") # == '\\s' in the js source bt("'\\\\\\s'") # == '\\\s' in the js source bt("'\\s'") # == '\s' in the js source bt('"•"') bt('"—"') bt('"\\x41\\x42\\x43\\x01"', '"\\x41\\x42\\x43\\x01"') bt('"\\u2022"', '"\\u2022"') bt('a = /\s+/') #bt('a = /\\x41/','a = /A/') bt('"\\u2022";a = /\s+/;"\\x41\\x42\\x43\\x01".match(/\\x41/);','"\\u2022";\na = /\s+/;\n"\\x41\\x42\\x43\\x01".match(/\\x41/);') test_fragment('"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff and \\xzz","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"', '"\\x22\\x27", \'\\x22\\x27\', "\\x5c", \'\\x5c\', "\\xff and \\xzz", "unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"') self.options.unescape_strings = True bt('"\\x41\\x42\\x43\\x01"', '"ABC\\x01"') test_fragment('"\\x20\\x40\\x4a"', '" @J"'); test_fragment('"\\xff\\x40\\x4a"'); test_fragment('"\\u0072\\u016B\\u0137\\u012B\\u0074\\u0069\\u0073"', six.u('"\u0072\u016B\u0137\u012B\u0074\u0069\u0073"')); bt('a = /\s+/') test_fragment('"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff"', '"\\"\\\'", \'\\"\\\'\', "\\\\", \'\\\\\', "\\xff", "unicode \\u0000 \\" \\\' \\\\ ' + unicode_char(0xffff) + '"'); # For error case, return the string unchanged test_fragment('"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff and \\xzz","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"', '"\\"\\\'", \'\\"\\\'\', "\\\\", \'\\\\\', "\\xff and \\xzz", "unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"'); self.options.unescape_strings = False def test_beautifier(self): test_fragment = self.decodesto bt = self.bt true = True false = False def unicode_char(value): return six.unichr(value) {{#groups}}{{#set_mustache_tags}}.{{/set_mustache_tags}} #============================================================ {{^matrix}} # {{&name}} self.reset_options(); {{#options}} self.options.{{name}} = {{&value}} {{/options}} {{#tests}} {{#test_line}}.{{/test_line}} {{/tests}} {{/matrix}} {{#matrix}} # {{&name}} - ({{#matrix_context_string}}.{{/matrix_context_string}}) self.reset_options(); {{#options}} self.options.{{name}} = {{&value}} {{/options}} {{#tests}} {{#test_line}}.{{/test_line}} {{/tests}} {{/matrix}} {{#unset_mustache_tags}}.{{/unset_mustache_tags}}{{/groups}} def test_beautifier_unconverted(self): test_fragment = self.decodesto bt = self.bt self.reset_options(); #============================================================ self.options.indent_size = 1; self.options.indent_char = ' '; bt('{ one_char() }', "{\n one_char()\n}") bt('var a,b=1,c=2', 'var a, b = 1,\n c = 2') self.options.indent_size = 4; self.options.indent_char = ' '; bt('{ one_char() }', "{\n one_char()\n}") self.options.indent_size = 1; self.options.indent_char = "\t"; bt('{ one_char() }', "{\n\tone_char()\n}") bt('x = a ? b : c; x;', 'x = a ? b : c;\nx;') #set to something else than it should change to, but with tabs on, should override self.options.indent_size = 5; self.options.indent_char = ' '; self.options.indent_with_tabs = True; bt('{ one_char() }', "{\n\tone_char()\n}") bt('x = a ? b : c; x;', 'x = a ? b : c;\nx;') self.reset_options(); #============================================================ self.options.preserve_newlines = False; bt('var\na=dont_preserve_newlines;', 'var a = dont_preserve_newlines;') # make sure the blank line between function definitions stays # even when preserve_newlines = False bt('function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}') bt('function foo() {\n return 1;\n}\nfunction foo() {\n return 1;\n}', 'function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}' ) bt('function foo() {\n return 1;\n}\n\n\nfunction foo() {\n return 1;\n}', 'function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}' ) self.options.preserve_newlines = True; bt('var\na=do_preserve_newlines;', 'var\n a = do_preserve_newlines;') bt('if (foo) // comment\n{\n bar();\n}') self.reset_options(); #============================================================ self.options.keep_array_indentation = False; bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f']", "a = ['a', 'b', 'c',\n 'd', 'e', 'f'\n]") bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i']", "a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i'\n]") bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i']", "a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i'\n]") bt('var x = [{}\n]', 'var x = [{}]') bt('var x = [{foo:bar}\n]', 'var x = [{\n foo: bar\n}]') bt("a = ['something',\n 'completely',\n 'different'];\nif (x);", "a = ['something',\n 'completely',\n 'different'\n];\nif (x);") bt("a = ['a','b','c']", "a = ['a', 'b', 'c']") bt("a = ['a', 'b','c']", "a = ['a', 'b', 'c']") bt("x = [{'a':0}]", "x = [{\n 'a': 0\n}]") bt('{a([[a1]], {b;});}', '{\n a([\n [a1]\n ], {\n b;\n });\n}') bt("a();\n [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();", "a();\n[\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n].toString();") bt("a();\na = [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();", "a();\na = [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n].toString();") bt("function() {\n Foo([\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ]);\n}", "function() {\n Foo([\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ]);\n}") bt('function foo() {\n return [\n "one",\n "two"\n ];\n}') # 4 spaces per indent input, processed with 4-spaces per indent bt( "function foo() {\n" + " return [\n" + " {\n" + " one: 'x',\n" + " two: [\n" + " {\n" + " id: 'a',\n" + " name: 'apple'\n" + " }, {\n" + " id: 'b',\n" + " name: 'banana'\n" + " }\n" + " ]\n" + " }\n" + " ];\n" + "}", "function foo() {\n" + " return [{\n" + " one: 'x',\n" + " two: [{\n" + " id: 'a',\n" + " name: 'apple'\n" + " }, {\n" + " id: 'b',\n" + " name: 'banana'\n" + " }]\n" + " }];\n" + "}") # 3 spaces per indent input, processed with 4-spaces per indent bt( "function foo() {\n" + " return [\n" + " {\n" + " one: 'x',\n" + " two: [\n" + " {\n" + " id: 'a',\n" + " name: 'apple'\n" + " }, {\n" + " id: 'b',\n" + " name: 'banana'\n" + " }\n" + " ]\n" + " }\n" + " ];\n" + "}", "function foo() {\n" + " return [{\n" + " one: 'x',\n" + " two: [{\n" + " id: 'a',\n" + " name: 'apple'\n" + " }, {\n" + " id: 'b',\n" + " name: 'banana'\n" + " }]\n" + " }];\n" + "}") self.options.keep_array_indentation = True; bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f']") bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i']") bt("a = ['a', 'b', 'c',\n 'd', 'e', 'f',\n 'g', 'h', 'i']") bt('var x = [{}\n]', 'var x = [{}\n]') bt('var x = [{foo:bar}\n]', 'var x = [{\n foo: bar\n }\n]') bt("a = ['something',\n 'completely',\n 'different'];\nif (x);") bt("a = ['a','b','c']", "a = ['a', 'b', 'c']") bt("a = ['a', 'b','c']", "a = ['a', 'b', 'c']") bt("x = [{'a':0}]", "x = [{\n 'a': 0\n}]") bt('{a([[a1]], {b;});}', '{\n a([[a1]], {\n b;\n });\n}') bt("a();\n [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();", "a();\n [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();") bt("a();\na = [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();", "a();\na = [\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ].toString();") bt("function() {\n Foo([\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ]);\n}", "function() {\n Foo([\n ['sdfsdfsd'],\n ['sdfsdfsdf']\n ]);\n}") bt('function foo() {\n return [\n "one",\n "two"\n ];\n}') # 4 spaces per indent input, processed with 4-spaces per indent bt( "function foo() {\n" + " return [\n" + " {\n" + " one: 'x',\n" + " two: [\n" + " {\n" + " id: 'a',\n" + " name: 'apple'\n" + " }, {\n" + " id: 'b',\n" + " name: 'banana'\n" + " }\n" + " ]\n" + " }\n" + " ];\n" + "}") # 3 spaces per indent input, processed with 4-spaces per indent # Should be unchanged, but is not - #445 # bt( "function foo() {\n" + # " return [\n" + # " {\n" + # " one: 'x',\n" + # " two: [\n" + # " {\n" + # " id: 'a',\n" + # " name: 'apple'\n" + # " }, {\n" + # " id: 'b',\n" + # " name: 'banana'\n" + # " }\n" + # " ]\n" + # " }\n" + # " ];\n" + # "}") self.reset_options(); #============================================================ bt('a = //comment\n /regex/;') bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a) {\n b;\n} else {\n c;\n}') bt('var a = new function();') test_fragment('new function') self.reset_options(); #============================================================ # START tests for brace positioning # If this is ever supported, update tests for each brace style. # test_fragment('return\n{', 'return\n{') # can't support this?, but that's an improbable and extreme case anyway. self.options.brace_style = 'expand'; bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}') bt('if(1){2}else{3}', "if (1)\n{\n 2\n}\nelse\n{\n 3\n}") bt('try{a();}catch(b){c();}catch(d){}finally{e();}', "try\n{\n a();\n}\ncatch (b)\n{\n c();\n}\ncatch (d)\n{}\nfinally\n{\n e();\n}") bt('if(a){b();}else if(c) foo();', "if (a)\n{\n b();\n}\nelse if (c) foo();") bt("if (a) {\n// comment\n}else{\n// comment\n}", "if (a)\n{\n // comment\n}\nelse\n{\n // comment\n}") # if/else statement with empty body bt('if (x) {y} else { if (x) {y}}', 'if (x)\n{\n y\n}\nelse\n{\n if (x)\n {\n y\n }\n}') bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a)\n{\n b;\n}\nelse\n{\n c;\n}') test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}', ' /*\n * xx\n */\n // xx\n if (foo)\n {\n bar();\n }') bt('if (foo)\n{}\nelse /regex/.test();') test_fragment('if (foo) {', 'if (foo)\n{') test_fragment('foo {', 'foo\n{') test_fragment('return {', 'return {') # return needs the brace. test_fragment('return /* inline */ {', 'return /* inline */ {') test_fragment('return;\n{', 'return;\n{') bt("throw {}") bt("throw {\n foo;\n}") bt('var foo = {}') bt('function x() {\n foo();\n}zzz', 'function x()\n{\n foo();\n}\nzzz') test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx') bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}') bt('var a = new function() {};') bt('var a = new function a() {};', 'var a = new function a()\n{};') bt('var a = new function()\n{};', 'var a = new function() {};') bt('var a = new function a()\n{};') bt('var a = new function a()\n {},\n b = new function b()\n {};') bt("foo({\n 'a': 1\n},\n10);", "foo(\n {\n 'a': 1\n },\n 10);") bt('(["foo","bar"]).each(function(i) {return i;});', '(["foo", "bar"]).each(function(i)\n{\n return i;\n});') bt('(function(i) {return i;})();', '(function(i)\n{\n return i;\n})();') bt( "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test(\n" + "/*Argument 1*/ {\n" + " 'Value1': '1'\n" + "},\n" + "/*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test(\n" + " /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test( /*Argument 1*/\n" + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */\n" + "{\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") self.options.brace_style = 'collapse'; bt('//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}') bt('if(1){2}else{3}', "if (1) {\n 2\n} else {\n 3\n}") bt('try{a();}catch(b){c();}catch(d){}finally{e();}', "try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}") bt('if(a){b();}else if(c) foo();', "if (a) {\n b();\n} else if (c) foo();") bt("if (a) {\n// comment\n}else{\n// comment\n}", "if (a) {\n // comment\n} else {\n // comment\n}") # if/else statement with empty body bt('if (x) {y} else { if (x) {y}}', 'if (x) {\n y\n} else {\n if (x) {\n y\n }\n}') bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a) {\n b;\n} else {\n c;\n}') test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}', ' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }') bt('if (foo) {} else /regex/.test();') test_fragment('if (foo) {', 'if (foo) {') test_fragment('foo {', 'foo {') test_fragment('return {', 'return {') # return needs the brace. test_fragment('return /* inline */ {', 'return /* inline */ {') test_fragment('return;\n{', 'return; {') bt("throw {}") bt("throw {\n foo;\n}") bt('var foo = {}') bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz') test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx') bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}') bt('var a = new function() {};') bt('var a = new function a() {};') bt('var a = new function()\n{};', 'var a = new function() {};') bt('var a = new function a()\n{};', 'var a = new function a() {};') bt('var a = new function a()\n {},\n b = new function b()\n {};', 'var a = new function a() {},\n b = new function b() {};') bt("foo({\n 'a': 1\n},\n10);", "foo({\n 'a': 1\n },\n 10);") bt('(["foo","bar"]).each(function(i) {return i;});', '(["foo", "bar"]).each(function(i) {\n return i;\n});') bt('(function(i) {return i;})();', '(function(i) {\n return i;\n})();') bt( "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test(\n" + "/*Argument 1*/ {\n" + " 'Value1': '1'\n" + "},\n" + "/*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test(\n" + " /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test( /*Argument 1*/\n" + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */\n" + "{\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") self.options.brace_style = "end-expand"; bt('//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}') bt('if(1){2}else{3}', "if (1) {\n 2\n}\nelse {\n 3\n}") bt('try{a();}catch(b){c();}catch(d){}finally{e();}', "try {\n a();\n}\ncatch (b) {\n c();\n}\ncatch (d) {}\nfinally {\n e();\n}") bt('if(a){b();}else if(c) foo();', "if (a) {\n b();\n}\nelse if (c) foo();") bt("if (a) {\n// comment\n}else{\n// comment\n}", "if (a) {\n // comment\n}\nelse {\n // comment\n}") # if/else statement with empty body bt('if (x) {y} else { if (x) {y}}', 'if (x) {\n y\n}\nelse {\n if (x) {\n y\n }\n}') bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a) {\n b;\n}\nelse {\n c;\n}') test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}', ' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }') bt('if (foo) {}\nelse /regex/.test();') test_fragment('if (foo) {', 'if (foo) {') test_fragment('foo {', 'foo {') test_fragment('return {', 'return {') # return needs the brace. test_fragment('return /* inline */ {', 'return /* inline */ {') test_fragment('return;\n{', 'return; {') bt("throw {}") bt("throw {\n foo;\n}") bt('var foo = {}') bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz') test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx') bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}') bt('var a = new function() {};') bt('var a = new function a() {};') bt('var a = new function()\n{};', 'var a = new function() {};') bt('var a = new function a()\n{};', 'var a = new function a() {};') bt('var a = new function a()\n {},\n b = new function b()\n {};', 'var a = new function a() {},\n b = new function b() {};') bt("foo({\n 'a': 1\n},\n10);", "foo({\n 'a': 1\n },\n 10);") bt('(["foo","bar"]).each(function(i) {return i;});', '(["foo", "bar"]).each(function(i) {\n return i;\n});') bt('(function(i) {return i;})();', '(function(i) {\n return i;\n})();') bt( "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test(\n" + "/*Argument 1*/ {\n" + " 'Value1': '1'\n" + "},\n" + "/*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test(\n" + " /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test( /*Argument 1*/\n" + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */\n" + "{\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") self.options.brace_style = 'none'; bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}') bt('if(1){2}else{3}', "if (1) {\n 2\n} else {\n 3\n}") bt('try{a();}catch(b){c();}catch(d){}finally{e();}', "try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}") bt('if(a){b();}else if(c) foo();', "if (a) {\n b();\n} else if (c) foo();") bt("if (a) {\n// comment\n}else{\n// comment\n}", "if (a) {\n // comment\n} else {\n // comment\n}") # if/else statement with empty body bt('if (x) {y} else { if (x) {y}}', 'if (x) {\n y\n} else {\n if (x) {\n y\n }\n}') bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}', 'if (a)\n{\n b;\n}\nelse\n{\n c;\n}') test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}', ' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }') bt('if (foo)\n{}\nelse /regex/.test();') test_fragment('if (foo) {') test_fragment('foo {') test_fragment('return {') # return needs the brace. test_fragment('return /* inline */ {') test_fragment('return;\n{') bt("throw {}") bt("throw {\n foo;\n}") bt('var foo = {}') bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz') test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx') bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}') bt('var a = new function() {};') bt('var a = new function a() {};') bt('var a = new function()\n{};', 'var a = new function() {};') bt('var a = new function a()\n{};') bt('var a = new function a()\n {},\n b = new function b()\n {};') bt("foo({\n 'a': 1\n},\n10);", "foo({\n 'a': 1\n },\n 10);") bt('(["foo","bar"]).each(function(i) {return i;});', '(["foo", "bar"]).each(function(i) {\n return i;\n});') bt('(function(i) {return i;})();', '(function(i) {\n return i;\n})();') bt( "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/ {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test(\n" + "/*Argument 1*/ {\n" + " 'Value1': '1'\n" + "},\n" + "/*Argument 2\n" + " */ {\n" + " 'Value2': '2'\n" + "});", # expected "test(\n" + " /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") bt( "test( /*Argument 1*/\n" + "{\n" + " 'Value1': '1'\n" + "}, /*Argument 2\n" + " */\n" + "{\n" + " 'Value2': '2'\n" + "});", # expected "test( /*Argument 1*/\n" + " {\n" + " 'Value1': '1'\n" + " },\n" + " /*Argument 2\n" + " */\n" + " {\n" + " 'Value2': '2'\n" + " });") # END tests for brace position self.reset_options(); #============================================================ test_fragment('roo = {\n /*\n ****\n FOO\n ****\n */\n BAR: 0\n};') test_fragment("if (zz) {\n // ....\n}\n(function") self.reset_options(); #============================================================ self.options.preserve_newlines = True; bt('var a = 42; // foo\n\nvar b;') bt('var a = 42; // foo\n\n\nvar b;') bt("var a = 'foo' +\n 'bar';") bt("var a = \"foo\" +\n \"bar\";") bt('"foo""bar""baz"', '"foo"\n"bar"\n"baz"') bt("'foo''bar''baz'", "'foo'\n'bar'\n'baz'") bt("{\n get foo() {}\n}") bt("{\n var a = get\n foo();\n}") bt("{\n set foo() {}\n}") bt("{\n var a = set\n foo();\n}") bt("var x = {\n get function()\n}") bt("var x = {\n set function()\n}") # According to my current research get/set have no special meaning outside of an object literal bt("var x = set\n\na() {}", "var x = set\n\na() {}") bt("var x = set\n\nfunction() {}", "var x = set\n\nfunction() {}") bt('') bt(' bt('for () /abc/.test()') bt('if (k) /aaa/m.test(v) && l();') bt('switch (true) {\n case /swf/i.test(foo):\n bar();\n}') bt('createdAt = {\n type: Date,\n default: Date.now\n}') bt('switch (createdAt) {\n case a:\n Date,\n default:\n Date.now\n}') bt('return function();') bt('var a = function();') bt('var a = 5 + function();') bt('{\n foo // something\n ,\n bar // something\n baz\n}') bt('function a(a) {} function b(b) {} function c(c) {}', 'function a(a) {}\n\nfunction b(b) {}\n\nfunction c(c) {}') bt('import foo.*;', 'import foo.*;') # actionscript's import test_fragment('function f(a: a, b: b)') # actionscript bt('foo(a, function() {})') bt('foo(a, /regex/)') bt('/* foo */\n"x"') self.reset_options(); #============================================================ self.options.break_chained_methods = False self.options.preserve_newlines = False bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)') bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar().baz().cucumber(fat)') bt('this.something.xxx = foo.moo.bar()') bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()') self.options.break_chained_methods = False self.options.preserve_newlines = True bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)') bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz().cucumber(fat)') bt('this.something.xxx = foo.moo.bar()') bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()') self.options.break_chained_methods = True self.options.preserve_newlines = False bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)') bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar()\n .baz()\n .cucumber(fat)') bt('this.something.xxx = foo.moo.bar()') bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()') self.options.break_chained_methods = True self.options.preserve_newlines = True bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)') bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)') bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz()\n .cucumber(fat)') bt('this.something.xxx = foo.moo.bar()') bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()') self.reset_options(); #============================================================ # Line wrap test intputs #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 wrap_input_1=('foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' + 'return between_return_and_expression_should_never_wrap.but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap.but_this_can\n' + 'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' + 'object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + '}') #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 wrap_input_2=('{\n' + ' foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + ' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' + ' return between_return_and_expression_should_never_wrap.but_this_can\n' + ' throw between_throw_and_expression_should_never_wrap.but_this_can\n' + ' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' + ' object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + ' }' + '}') self.options.preserve_newlines = False self.options.wrap_line_length = 0 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' + 'return between_return_and_expression_should_never_wrap.but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap.but_this_can\n' + 'if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' + 'object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + '}') self.options.wrap_line_length = 70 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' + 'return between_return_and_expression_should_never_wrap.but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap.but_this_can\n' + 'if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' + 'object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + '}') self.options.wrap_line_length = 40 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat &&\n' + ' "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_.okay();\n' + 'object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + '}') self.options.wrap_line_length = 41 # NOTE: wrap is only best effort - line continues until next wrap point is found. #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") ||\n' + ' (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_.okay();\n' + 'object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + '}') self.options.wrap_line_length = 45 # NOTE: wrap is only best effort - line continues until next wrap point is found. #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_2, # expected # '{\n' + ' foo.bar().baz().cucumber((fat && "sassy") ||\n' + ' (leans && mean));\n' + ' Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + ' return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + ' throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + ' if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_.okay();\n' + ' object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + ' }\n'+ '}') self.options.preserve_newlines = True self.options.wrap_line_length = 0 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap.but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap.but_this_can\n' + 'if (wraps_can_occur && inside_an_if_block) that_is_\n' + ' .okay();\n' + 'object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + '}') self.options.wrap_line_length = 70 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap.but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap.but_this_can\n' + 'if (wraps_can_occur && inside_an_if_block) that_is_\n' + ' .okay();\n' + 'object_literal = {\n' + ' propertx: first_token + 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap + but_this_can,\n' + ' propertz: first_token_should_never_wrap + !but_this_can,\n' + ' proper: "first_token_should_never_wrap" + "but_this_can"\n' + '}') self.options.wrap_line_length = 40 #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat &&\n' + ' "sassy") || (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_\n' + ' .okay();\n' + 'object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + '}') self.options.wrap_line_length = 41 # NOTE: wrap is only best effort - line continues until next wrap point is found. #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_1, # expected # 'foo.bar().baz().cucumber((fat && "sassy") ||\n' + ' (leans && mean));\n' + 'Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + 'return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + 'if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_\n' + ' .okay();\n' + 'object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + '}') self.options.wrap_line_length = 45 # NOTE: wrap is only best effort - line continues until next wrap point is found. #..............---------1---------2---------3---------4---------5---------6---------7 #..............1234567890123456789012345678901234567890123456789012345678901234567890 test_fragment(wrap_input_2, # expected # '{\n' + ' foo.bar().baz().cucumber((fat && "sassy") ||\n' + ' (leans && mean));\n' + ' Test_very_long_variable_name_this_should_never_wrap\n' + ' .but_this_can\n' + ' return between_return_and_expression_should_never_wrap\n' + ' .but_this_can\n' + ' throw between_throw_and_expression_should_never_wrap\n' + ' .but_this_can\n' + ' if (wraps_can_occur &&\n' + ' inside_an_if_block) that_is_\n' + ' .okay();\n' + ' object_literal = {\n' + ' propertx: first_token +\n' + ' 12345678.99999E-6,\n' + ' property: first_token_should_never_wrap +\n' + ' but_this_can,\n' + ' propertz: first_token_should_never_wrap +\n' + ' !but_this_can,\n' + ' proper: "first_token_should_never_wrap" +\n' + ' "but_this_can"\n' + ' }\n'+ '}') self.reset_options(); #============================================================ self.options.preserve_newlines = False bt('if (foo) // comment\n bar();') bt('if (foo) // comment\n (bar());') bt('if (foo) // comment\n (bar());') bt('if (foo) // comment\n /asdf/;') bt('this.oa = new OAuth(\n' + ' _requestToken,\n' + ' _accessToken,\n' + ' consumer_key\n' + ');', 'this.oa = new OAuth(_requestToken, _accessToken, consumer_key);') bt('foo = {\n x: y, // #44\n w: z // #44\n}') bt('switch (x) {\n case "a":\n // comment on newline\n break;\n case "b": // comment on same line\n break;\n}') bt('this.type =\n this.options =\n // comment\n this.enabled null;', 'this.type = this.options =\n // comment\n this.enabled null;') bt('someObj\n .someFunc1()\n // This comment should not break the indent\n .someFunc2();', 'someObj.someFunc1()\n // This comment should not break the indent\n .someFunc2();') bt('if (true ||\n!true) return;', 'if (true || !true) return;') # these aren't ready yet. #bt('if (foo) // comment\n bar() /*i*/ + baz() /*j\n*/ + asdf();') bt('if\n(foo)\nif\n(bar)\nif\n(baz)\nwhee();\na();', 'if (foo)\n if (bar)\n if (baz) whee();\na();') bt('if\n(foo)\nif\n(bar)\nif\n(baz)\nwhee();\nelse\na();', 'if (foo)\n if (bar)\n if (baz) whee();\n else a();') bt('if (foo)\nbar();\nelse\ncar();', 'if (foo) bar();\nelse car();') bt('if (foo) if (bar) if (baz);\na();', 'if (foo)\n if (bar)\n if (baz);\na();') bt('if (foo) if (bar) if (baz) whee();\na();', 'if (foo)\n if (bar)\n if (baz) whee();\na();') bt('if (foo) a()\nif (bar) if (baz) whee();\na();', 'if (foo) a()\nif (bar)\n if (baz) whee();\na();') bt('if (foo);\nif (bar) if (baz) whee();\na();', 'if (foo);\nif (bar)\n if (baz) whee();\na();') bt('if (options)\n' + ' for (var p in options)\n' + ' this[p] = options[p];', 'if (options)\n'+ ' for (var p in options) this[p] = options[p];') bt('if (options) for (var p in options) this[p] = options[p];', 'if (options)\n for (var p in options) this[p] = options[p];') bt('if (options) do q(); while (b());', 'if (options)\n do q(); while (b());') bt('if (options) while (b()) q();', 'if (options)\n while (b()) q();') bt('if (options) do while (b()) q(); while (a());', 'if (options)\n do\n while (b()) q(); while (a());') bt('function f(a, b, c,\nd, e) {}', 'function f(a, b, c, d, e) {}') bt('function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}', 'function f(a, b) {\n if (a) b()\n}\n\nfunction g(a, b) {\n if (!a) b()\n}') bt('function f(a,b) {if(a) b()}\n\n\n\nfunction g(a,b) {if(!a) b()}', 'function f(a, b) {\n if (a) b()\n}\n\nfunction g(a, b) {\n if (!a) b()\n}') # This is not valid syntax, but still want to behave reasonably and not side-effect bt('(if(a) b())(if(a) b())', '(\n if (a) b())(\n if (a) b())') bt('(if(a) b())\n\n\n(if(a) b())', '(\n if (a) b())\n(\n if (a) b())') # space between functions bt('/*\n * foo\n */\nfunction foo() {}') bt('// a nice function\nfunction foo() {}') bt('function foo() {}\nfunction foo() {}', 'function foo() {}\n\nfunction foo() {}' ) bt('[\n function() {}\n]') bt("if\n(a)\nb();", "if (a) b();") bt('var a =\nfoo', 'var a = foo') bt('var a = {\n"a":1,\n"b":2}', "var a = {\n \"a\": 1,\n \"b\": 2\n}") bt("var a = {\n'a':1,\n'b':2}", "var a = {\n 'a': 1,\n 'b': 2\n}") bt('var a = /*i*/ "b";') bt('var a = /*i*/\n"b";', 'var a = /*i*/ "b";') bt('var a = /*i*/\nb;', 'var a = /*i*/ b;') bt('{\n\n\n"x"\n}', '{\n "x"\n}') bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a && b || c || d && e) e = f') bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a && (b || c || d) && e) e = f') test_fragment('\n\n"x"', '"x"') bt('a = 1;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nb = 2;', 'a = 1;\nb = 2;') self.options.preserve_newlines = True bt('if (foo) // comment\n bar();') bt('if (foo) // comment\n (bar());') bt('if (foo) // comment\n (bar());') bt('if (foo) // comment\n /asdf/;') bt('this.oa = new OAuth(\n' + ' _requestToken,\n' + ' _accessToken,\n' + ' consumer_key\n' + ');') bt('foo = {\n x: y, // #44\n w: z // #44\n}') bt('switch (x) {\n case "a":\n // comment on newline\n break;\n case "b": // comment on same line\n break;\n}') bt('this.type =\n this.options =\n // comment\n this.enabled null;') bt('someObj\n .someFunc1()\n // This comment should not break the indent\n .someFunc2();') bt('if (true ||\n!true) return;', 'if (true ||\n !true) return;') # these aren't ready yet. # bt('if (foo) // comment\n bar() /*i*/ + baz() /*j\n*/ + asdf();') bt('if\n(foo)\nif\n(bar)\nif\n(baz)\nwhee();\na();', 'if (foo)\n if (bar)\n if (baz)\n whee();\na();') bt('if\n(foo)\nif\n(bar)\nif\n(baz)\nwhee();\nelse\na();', 'if (foo)\n if (bar)\n if (baz)\n whee();\n else\n a();') bt('if (foo)\nbar();\nelse\ncar();', 'if (foo)\n bar();\nelse\n car();') bt('if (foo) bar();\nelse\ncar();', 'if (foo) bar();\nelse\n car();') bt('if (foo) if (bar) if (baz);\na();', 'if (foo)\n if (bar)\n if (baz);\na();') bt('if (foo) if (bar) if (baz) whee();\na();', 'if (foo)\n if (bar)\n if (baz) whee();\na();') bt('if (foo) a()\nif (bar) if (baz) whee();\na();', 'if (foo) a()\nif (bar)\n if (baz) whee();\na();') bt('if (foo);\nif (bar) if (baz) whee();\na();', 'if (foo);\nif (bar)\n if (baz) whee();\na();') bt('if (options)\n' + ' for (var p in options)\n' + ' this[p] = options[p];') bt('if (options) for (var p in options) this[p] = options[p];', 'if (options)\n for (var p in options) this[p] = options[p];') bt('if (options) do q(); while (b());', 'if (options)\n do q(); while (b());') bt('if (options) do; while (b());', 'if (options)\n do; while (b());') bt('if (options) while (b()) q();', 'if (options)\n while (b()) q();') bt('if (options) do while (b()) q(); while (a());', 'if (options)\n do\n while (b()) q(); while (a());') bt('function f(a, b, c,\nd, e) {}', 'function f(a, b, c,\n d, e) {}') bt('function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}', 'function f(a, b) {\n if (a) b()\n}\n\nfunction g(a, b) {\n if (!a) b()\n}') bt('function f(a,b) {if(a) b()}\n\n\n\nfunction g(a,b) {if(!a) b()}', 'function f(a, b) {\n if (a) b()\n}\n\n\n\nfunction g(a, b) {\n if (!a) b()\n}') # This is not valid syntax, but still want to behave reasonably and not side-effect bt('(if(a) b())(if(a) b())', '(\n if (a) b())(\n if (a) b())') bt('(if(a) b())\n\n\n(if(a) b())', '(\n if (a) b())\n\n\n(\n if (a) b())') bt("if\n(a)\nb();", "if (a)\n b();") bt('var a =\nfoo', 'var a =\n foo') bt('var a = {\n"a":1,\n"b":2}', "var a = {\n \"a\": 1,\n \"b\": 2\n}") bt("var a = {\n'a':1,\n'b':2}", "var a = {\n 'a': 1,\n 'b': 2\n}") bt('var a = /*i*/ "b";') bt('var a = /*i*/\n"b";', 'var a = /*i*/\n "b";') bt('var a = /*i*/\nb;', 'var a = /*i*/\n b;') bt('{\n\n\n"x"\n}', '{\n\n\n "x"\n}') bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a &&\n b ||\n c ||\n d &&\n e) e = f') bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a &&\n (b ||\n c ||\n d) &&\n e) e = f') test_fragment('\n\n"x"', '"x"') # this beavior differs between js and python, defaults to unlimited in js, 10 in python bt('a = 1;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nb = 2;', 'a = 1;\n\n\n\n\n\n\n\n\n\nb = 2;') self.options.max_preserve_newlines = 8; bt('a = 1;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nb = 2;', 'a = 1;\n\n\n\n\n\n\n\nb = 2;') self.reset_options(); #============================================================ def decodesto(self, input, expectation=None): if expectation == None: expectation = input self.assertMultiLineEqual( jsbeautifier.beautify(input, self.options), expectation) # if the expected is different from input, run it again # expected output should be unchanged when run twice. if not expectation == None: self.assertMultiLineEqual( jsbeautifier.beautify(expectation, self.options), expectation) # Everywhere we do newlines, they should be replaced with opts.eol self.options.eol = '\r\\n'; expectation = expectation.replace('\n', '\r\n') self.assertMultiLineEqual( jsbeautifier.beautify(input, self.options), expectation) if input.find('\n') != -1: input = input.replace('\n', '\r\n') self.assertMultiLineEqual( jsbeautifier.beautify(input, self.options), expectation) # Ensure support for auto eol detection self.options.eol = 'auto' self.assertMultiLineEqual( jsbeautifier.beautify(input, self.options), expectation) self.options.eol = '\n' def wrap(self, text): return self.wrapregex.sub(' \\1', text) def bt(self, input, expectation=None): if expectation == None: expectation = input self.decodesto(input, expectation) # If we set raw, input should be unchanged self.options.test_output_raw = True if self.options.end_with_newline: elf.decodesto(input, input) self.options.test_output_raw = False current_indent_size = None if self.options.js and self.options.js['indent_size']: current_indent_size = self.options.js['indent_size'] if not current_indent_size: current_indent_size = self.options.indent_size if current_indent_size == 4 and input: wrapped_input = '{\n%s\n foo = bar;\n}' % self.wrap(input) wrapped_expect = '{\n%s\n foo = bar;\n}' % self.wrap(expectation) self.decodesto(wrapped_input, wrapped_expect) # If we set raw, input should be unchanged self.options.test_output_raw = True if self.options.end_with_newline: elf.decodesto(wrapped_input, wrapped_input) self.options.test_output_raw = False if __name__ == '__main__': unittest.main()