/test/test.js

https://gitlab.com/Jerry-Lau/buble · JavaScript · 303 lines · 63 code · 14 blank · 226 comment · 7 complexity · 0a0f8ce714a112f9da278b917e4afbe2 MD5 · raw file

  1. var path = require( 'path' );
  2. var fs = require( 'fs' );
  3. var rimraf = require( 'rimraf' );
  4. var child_process = require( 'child_process' );
  5. var assert = require( 'assert' );
  6. var glob = require( 'glob' );
  7. var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer;
  8. var getLocation = require( './utils/getLocation.js' );
  9. var buble = require( '../dist/buble.umd.js' );
  10. require( 'source-map-support' ).install();
  11. function equal ( a, b ) {
  12. assert.equal( showInvisibles( a ), showInvisibles( b ) );
  13. }
  14. function showInvisibles ( str ) {
  15. return str
  16. .replace( /^ +/gm, spaces => repeat( '•', spaces.length ) )
  17. .replace( / +$/gm, spaces => repeat( '•', spaces.length ) )
  18. .replace( /^\t+/gm, tabs => repeat( '› ', tabs.length ) )
  19. .replace( /\t+$/gm, tabs => repeat( '› ', tabs.length ) );
  20. }
  21. function repeat ( str, times ) {
  22. var result = '';
  23. while ( times-- ) result += str;
  24. return result;
  25. }
  26. describe( 'buble', () => {
  27. fs.readdirSync( 'test/samples' ).forEach( file => {
  28. var samples = require( './samples/' + file );
  29. describe( path.basename( file ), () => {
  30. samples.forEach( sample => {
  31. ( sample.solo ? it.only : sample.skip ? it.skip : it )( sample.description, () => {
  32. if ( sample.error ) {
  33. assert.throws( () => {
  34. buble.transform( sample.input, sample.options );
  35. }, sample.error );
  36. }
  37. else {
  38. equal( buble.transform( sample.input, sample.options ).code, sample.output );
  39. }
  40. });
  41. });
  42. });
  43. });
  44. describe( 'cli', () => {
  45. fs.readdirSync( 'test/cli' ).forEach( dir => {
  46. if ( dir[0] === '.' ) return; // .DS_Store
  47. it( dir, done => {
  48. dir = path.resolve( 'test/cli', dir );
  49. rimraf.sync( path.resolve( dir, 'actual' ) );
  50. fs.mkdirSync( path.resolve( dir, 'actual' ) );
  51. var binFile = path.resolve(__dirname, '../bin/buble');
  52. var commandFile = path.resolve( dir, 'command.sh' );
  53. var command = fs.readFileSync( commandFile, 'utf-8' )
  54. .replace( 'buble', 'node ' + binFile );
  55. child_process.exec( command, {
  56. cwd: dir
  57. }, ( err, stdout, stderr ) => {
  58. if ( err ) return done( err );
  59. if ( stdout ) console.log( stdout );
  60. if ( stderr ) console.error( stderr );
  61. function catalogue ( subdir ) {
  62. subdir = path.resolve( dir, subdir );
  63. return glob.sync( '**/*.js?(.map)', { cwd: subdir })
  64. .sort()
  65. .map( name => {
  66. var contents = fs.readFileSync( path.resolve( subdir, name ), 'utf-8' ).trim();
  67. if ( path.extname( name ) === '.map' ) {
  68. contents = JSON.parse( contents );
  69. }
  70. return {
  71. name: name,
  72. contents: contents
  73. };
  74. });
  75. }
  76. var expected = catalogue( 'expected' );
  77. var actual = catalogue( 'actual' );
  78. try {
  79. assert.deepEqual( actual, expected );
  80. done();
  81. } catch ( err ) {
  82. done( err );
  83. }
  84. });
  85. });
  86. });
  87. });
  88. describe( 'errors', () => {
  89. it( 'reports the location of a syntax error', () => {
  90. var source = `var 42 = nope;`;
  91. try {
  92. buble.transform( source );
  93. } catch ( err ) {
  94. assert.equal( err.name, 'SyntaxError' );
  95. assert.deepEqual( err.loc, { line: 1, column: 4 });
  96. assert.equal( err.message, 'Unexpected token (1:4)' );
  97. assert.equal( err.snippet, `1 : var 42 = nope;\n ^` );
  98. }
  99. });
  100. it( 'reports the location of a compile error', () => {
  101. var source = `const x = 1; x++;`;
  102. try {
  103. buble.transform( source );
  104. } catch ( err ) {
  105. assert.equal( err.name, 'CompileError' );
  106. assert.equal( err.loc.line, 1 );
  107. assert.equal( err.loc.column, 13 );
  108. assert.equal( err.message, 'x is read-only (1:13)' );
  109. assert.equal( err.snippet, `1 : const x = 1; x++;\n ^^^` );
  110. }
  111. });
  112. });
  113. describe( 'target', () => {
  114. it( 'determines necessary transforms for a target environment', () => {
  115. var transforms = buble.target({ chrome: 49 });
  116. assert.ok( transforms.moduleImport );
  117. assert.ok( !transforms.arrow );
  118. });
  119. it( 'returns lowest common denominator support info', () => {
  120. var transforms = buble.target({ chrome: 49, node: 5 });
  121. assert.ok( transforms.defaultParameter );
  122. assert.ok( !transforms.arrow );
  123. });
  124. it( 'only applies necessary transforms', () => {
  125. var source = `
  126. const power = ( base, exponent = 2 ) => Math.pow( base, exponent );`;
  127. var result = buble.transform( source, {
  128. target: { chrome: 49, node: 5 }
  129. }).code;
  130. assert.equal( result, `
  131. const power = ( base, exponent ) => {
  132. if ( exponent === void 0 ) exponent = 2;
  133. return Math.pow( base, exponent );
  134. };` );
  135. });
  136. });
  137. describe( 'sourcemaps', () => {
  138. it( 'generates a valid sourcemap', () => {
  139. var map = buble.transform( '' ).map;
  140. assert.equal( map.version, 3 );
  141. });
  142. it( 'uses provided file and source', () => {
  143. var map = buble.transform( '', {
  144. file: 'output.js',
  145. source: 'input.js'
  146. }).map;
  147. assert.equal( map.file, 'output.js' );
  148. assert.deepEqual( map.sources, [ 'input.js' ] );
  149. });
  150. it( 'includes content by default', () => {
  151. var source = `let { x, y } = foo();`;
  152. var map = buble.transform( source ).map;
  153. assert.deepEqual( map.sourcesContent, [ source ] );
  154. });
  155. it( 'excludes content if requested', () => {
  156. var source = `let { x, y } = foo();`;
  157. var map = buble.transform( source, {
  158. includeContent: false
  159. }).map;
  160. assert.deepEqual( map.sourcesContent, [ null ] );
  161. });
  162. it( 'locates original content', () => {
  163. var source = `const add = ( a, b ) => a + b;`;
  164. var result = buble.transform( source, {
  165. file: 'output.js',
  166. source: 'input.js'
  167. });
  168. var smc = new SourceMapConsumer( result.map );
  169. var location = getLocation( result.code, 'add' );
  170. var expected = getLocation( source, 'add' );
  171. var actual = smc.originalPositionFor( location );
  172. assert.deepEqual( actual, {
  173. line: expected.line,
  174. column: expected.column,
  175. source: 'input.js',
  176. name: null
  177. });
  178. location = getLocation( result.code, 'a +' );
  179. expected = getLocation( source, 'a +' );
  180. actual = smc.originalPositionFor( location );
  181. assert.deepEqual( actual, {
  182. line: expected.line,
  183. column: expected.column,
  184. source: 'input.js',
  185. name: null
  186. });
  187. });
  188. it( 'recovers names', () => {
  189. var source = `
  190. const foo = 1;
  191. if ( x ) {
  192. const foo = 2;
  193. }`;
  194. var result = buble.transform( source, {
  195. file: 'output.js',
  196. source: 'input.js'
  197. });
  198. var smc = new SourceMapConsumer( result.map );
  199. var location = getLocation( result.code, 'var' );
  200. var actual = smc.originalPositionFor( location );
  201. assert.equal( actual.name, 'const' );
  202. location = getLocation( result.code, 'var', location.char + 1 );
  203. actual = smc.originalPositionFor( location );
  204. assert.equal( actual.name, 'const' );
  205. location = getLocation( result.code, 'foo$1', location.char + 1 );
  206. actual = smc.originalPositionFor( location );
  207. assert.equal( actual.name, 'foo' );
  208. });
  209. it( 'handles moved content', () => {
  210. var source = `
  211. for ( let i = 0; i < 10; i += 1 ) {
  212. const square = i * i;
  213. setTimeout( function () {
  214. log( square );
  215. }, i * 100 );
  216. }`;
  217. var result = buble.transform( source, {
  218. file: 'output.js',
  219. source: 'input.js'
  220. });
  221. var smc = new SourceMapConsumer( result.map );
  222. var location = getLocation( result.code, 'i < 10' );
  223. var expected = getLocation( source, 'i < 10' );
  224. var actual = smc.originalPositionFor( location );
  225. assert.deepEqual( actual, {
  226. line: expected.line,
  227. column: expected.column,
  228. source: 'input.js',
  229. name: null
  230. });
  231. location = getLocation( result.code, 'setTimeout' );
  232. expected = getLocation( source, 'setTimeout' );
  233. actual = smc.originalPositionFor( location );
  234. assert.deepEqual( actual, {
  235. line: expected.line,
  236. column: expected.column,
  237. source: 'input.js',
  238. name: null
  239. });
  240. });
  241. });
  242. });