├── .gitignore ├── .jshintrc ├── .travis.yml ├── CHANGELOG.md ├── MIT-LICENSE.txt ├── README.md ├── gulpfile.js ├── index.js ├── package-lock.json ├── package.json └── test ├── expected ├── customized.js ├── es2018.js ├── example.js ├── example_without_filepath_and_sourcemap.js ├── with-file-sourcemap.js └── with-sourcemap.js ├── fixtures ├── customized.js ├── es2018.js ├── example.js ├── with-file-sourcemap.js ├── with-file-sourcemap.js.map └── with-sourcemap.js ├── paths_test.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "eqnull": true, 7 | "esnext": true, 8 | "evil": true, 9 | "forin": false, 10 | "immed": true, 11 | "indent": 4, 12 | "latedef": false, 13 | "maxdepth": 4, 14 | "maxparams": 4, 15 | "newcap": true, 16 | "noarg": true, 17 | "node": true, 18 | "nonew": true, 19 | "onevar": true, 20 | "quotmark": "single", 21 | "smarttabs": true, 22 | "strict": true, 23 | "trailing": true, 24 | "undef": true, 25 | "unused": "vars", 26 | "white": true 27 | } 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "8" # to be removed on "December 2019" 5 | - "10" # to be removed on "April 2021" 6 | - "12" # to be removed on "April 2022" 7 | - "13" # to be removed on "June 2020" 8 | script: 9 | - "npm run lint" 10 | - "npm test" 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.3.0](https://github.com/power-assert-js/espower-source/releases/tag/v2.3.0) (2018-06-12) 2 | 3 | 4 | #### Features 5 | 6 | * [Support ES2018 syntax](https://github.com/power-assert-js/espower-source/pull/20) 7 | 8 | 9 | ## [2.2.0](https://github.com/power-assert-js/espower-source/releases/tag/v2.2.0) (2017-05-05) 10 | 11 | 12 | #### Features 13 | 14 | * [add `ecmaVersion` and `sourceType` to options](https://github.com/power-assert-js/espower-source/pull/17) 15 | * [add `sourceRoot` property to generated SourceMap](https://github.com/power-assert-js/espower-source/pull/18) 16 | 17 | 18 | ## [2.1.0](https://github.com/power-assert-js/espower-source/releases/tag/v2.1.0) (2017-04-09) 19 | 20 | 21 | #### Features 22 | 23 | * [support file SourceMap](https://github.com/power-assert-js/espower-source/pull/14) by [@shepherdwind](https://github.com/shepherdwind) 24 | 25 | 26 | ### [2.0.1](https://github.com/power-assert-js/espower-source/releases/tag/v2.0.1) (2017-02-13) 27 | 28 | 29 | #### Bug Fixes 30 | 31 | * [fix: ecmaVersion 7 => 2017 to support async await](https://github.com/power-assert-js/espower-source/pull/13) by [@dead-horse](https://github.com/dead-horse) 32 | 33 | 34 | ## [2.0.0](https://github.com/power-assert-js/espower-source/releases/tag/v2.0.0) (2016-11-12) 35 | 36 | 37 | #### Features 38 | 39 | * [Integrate `empower-assert` to enable transparent assertion enhancement](https://github.com/power-assert-js/espower-source/pull/11) 40 | * Embed value capturing helper into transpiled code (by upgrading espower to 2.0.0) ([78a57687](https://github.com/power-assert-js/espower-source/commit/78a57687b142ae99a0eae3566042a1467c016b1e)) 41 | 42 | 43 | #### Breaking Changes 44 | 45 | * [Drop support for prebuilt bundle, bower, and Node v0.10](https://github.com/power-assert-js/espower-source/pull/12) 46 | 47 | We stopped providing prebuilt bundle for browsers. Please build your own by using browserify, webpack and so on. 48 | We also dropped bower support. Please use npm instead. 49 | 50 | 51 | ## [1.2.0](https://github.com/power-assert-js/espower-source/releases/tag/v1.2.0) (2016-10-25) 52 | 53 | 54 | #### Features 55 | 56 | * [show SyntaxError detail](https://github.com/power-assert-js/espower-source/pull/10) (by [@shibukawa](https://github.com/shibukawa)) 57 | 58 | 59 | ## [1.1.0](https://github.com/power-assert-js/espower-source/releases/tag/v1.1.0) (2016-01-22) 60 | 61 | 62 | #### Bug Fixes 63 | 64 | * relax too strict originalCode checking ([458ef9f1](https://github.com/power-assert-js/espower-source/commit/458ef9f1e916e3496945f046bafd36497c08fe10)) 65 | 66 | 67 | #### Features 68 | 69 | * [add async-await support](https://github.com/power-assert-js/espower-source/pull/8) (by [@jamestalmage](https://github.com/jamestalmage)) 70 | 71 | 72 | ## [1.0.0](https://github.com/power-assert-js/espower-source/releases/tag/v1.0.0) (2015-08-08) 73 | 74 | 75 | #### Bug Fixes 76 | 77 | * properties of outgoing SourceMap is broken when `typeof options.sourceMap` is string ([af6ba419](https://github.com/power-assert-js/espower-source/commit/af6ba419fb01ee79a4fefe4c3acc23d94bd7c1b3)) 78 | * preserve sourceRoot if incoming sourceMap contains sourceRoot ([c95e3252](https://github.com/power-assert-js/espower-source/commit/c95e32520335556b41dff73c692b5a22dc105950)) 79 | 80 | #### Features 81 | 82 | * transfer to power-assert-js organization ([ff22316e](https://github.com/power-assert-js/espower-source/commit/ff22316eb0c45bf5ec4bb91cadc13005cfd23d30)) 83 | * ship bundle for browsers with npm module ([36b4ed84](https://github.com/power-assert-js/espower-source/commit/36b4ed845048edc7749d6c0f3e61db29dfe74d21)) 84 | * [sourceRoot option](https://github.com/power-assert-js/espower-source/pull/7) 85 | * throw EspowerError when `originalCode` is not specified ([04d86abb](https://github.com/power-assert-js/espower-source/commit/04d86abb40af1499fde55a419346666d3b90d35a)) 86 | * clarify parameter prerequisite and its outcome ([95ed841b](https://github.com/power-assert-js/espower-source/commit/95ed841bdde5bf422fa63b0680f75d4ac82b6b74)) 87 | 88 | 89 | ## [0.10.0](https://github.com/power-assert-js/espower-source/releases/tag/v0.10.0) (2014-11-11) 90 | 91 | 92 | * **espower-source:** 93 | * update espower to 0.10.0 ([cd05911e](https://github.com/power-assert-js/espower-source/commit/cd05911e9199ea079f8522348624387b92a97208)) 94 | 95 | 96 | ### 0.9.1 (2014-09-15) 97 | 98 | 99 | #### Features 100 | 101 | * **espower-source:** update espower to 0.9.1 ([8acad23d](https://github.com/power-assert-js/espower-source/commit/8acad23d1eeb613c539ed1dba09830b86e932c0f)) 102 | 103 | 104 | ## 0.9.0 (2014-08-31) 105 | 106 | 107 | #### Features 108 | 109 | * **espower-source:** backport espowerify to support multi-stage sourcemaps ([71de737c](https://github.com/power-assert-js/espower-source/commit/71de737cb16231db852a44592e896a43c447298b)) 110 | 111 | 112 | ## 0.8.0 (2014-08-12) 113 | 114 | 115 | #### Features 116 | 117 | * **espower-source:** 118 | * update espower to 0.8.0 ([ae15a229](https://github.com/power-assert-js/espower-source/commit/ae15a229367c65a7a590104f3fb0fc0b2a7582d0)) 119 | * simple xtend would be better for options handling ([6bea0a92](https://github.com/power-assert-js/espower-source/commit/6bea0a9241aba71f2dcae9c285561e68d91531bb)) 120 | 121 | 122 | #### Breaking Changes 123 | 124 | * update espower to 0.8.0 ([ae15a229](https://github.com/power-assert-js/espower-source/commit/ae15a229367c65a7a590104f3fb0fc0b2a7582d0)) 125 | 126 | If you already customize instrumentation pattern using `powerAssertVariableName` and `targetMethods`, you need to migarte. To migrate, change your code from the following: 127 | 128 | ```javascript 129 | var espowerSource = require('espower-source'); 130 | var options = { 131 | powerAssertVariableName: 'yourAssert', 132 | targetMethods: { 133 | oneArg: [ 134 | 'okay' 135 | ], 136 | twoArgs: [ 137 | 'equal', 138 | 'customEqual' 139 | ] 140 | } 141 | }; 142 | var modifiedCode = espowerSource(originalCode, filepath, options); 143 | ``` 144 | 145 | To: 146 | 147 | ```javascript 148 | var espowerSource = require('espower-source'); 149 | var options = { 150 | patterns: [ 151 | 'yourAssert(value, [message])', 152 | 'yourAssert.okay(value, [message])', 153 | 'yourAssert.equal(actual, expected, [message])', 154 | 'yourAssert.customEqual(actual, expected, [message])' 155 | ] 156 | }; 157 | var modifiedCode = espowerSource(originalCode, filepath, options); 158 | ``` 159 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2018 Takuto Wada, https://github.com/power-assert-js/espower-source 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | espower-source 2 | ================================ 3 | 4 | [![Build Status][travis-image]][travis-url] 5 | [![NPM package][npm-image]][npm-url] 6 | [![Dependency Status][depstat-image]][depstat-url] 7 | [![License][license-image]][license-url] 8 | 9 | 10 | Power Assert instrumentor from code to code, with SourceMap. 11 | 12 | 13 | DESCRIPTION 14 | --------------------------------------- 15 | `espower-source` is a source code transformer that applies [espower](https://github.com/power-assert-js/espower) to target code. 16 | 17 | `espower` manipulates assertion expression in the form of ECMAScript AST defined in [The ESTree Spec](https://github.com/estree/estree) (formerly known as [Mozilla SpiderMonkey Parser API](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)), to instrument power-assert feature into the code. SourceMap information is appended in SourceMap Comment syntax at the end of returned code. 18 | 19 | Pull-requests, issue reports and patches are always welcomed. See [power-assert](https://github.com/power-assert-js/power-assert) project for more documentation. 20 | 21 | 22 | CHANGELOG 23 | --------------------------------------- 24 | See [CHANGELOG](https://github.com/power-assert-js/espower-source/blob/master/CHANGELOG.md) 25 | 26 | 27 | API 28 | --------------------------------------- 29 | 30 | ### var modifiedCode = espowerSource(originalCode, [filepath], [options]) 31 | 32 | | return type | 33 | |:------------| 34 | | `string` | 35 | 36 | `espowerSource` function manipulates `originalCode` then returns (transformed) JavaScript code as string. SourceMap information is appended in SourceMap Comment syntax at the end of returned code. 37 | 38 | #### originalCode 39 | 40 | | type | default value | 41 | |:---------|:--------------| 42 | | `string` | N/A | 43 | 44 | Original JavaScript source code that is a source of code transformation. If not specified, then `EspowerError` will be thrown. 45 | 46 | #### filepath (optional but recommended) 47 | 48 | | type | default value | 49 | |:---------|:--------------| 50 | | `string` | N/A | 51 | 52 | Filepath of `originalCode`. espower-source stores filepath information for later reporting. If not specified, `options.path` will be used. If neither filepath nor options.path are not specified, espower-source transforms code as usual but SourceMap will not be generated and attached. 53 | 54 | #### options (optional) 55 | 56 | | type | default value | 57 | |:---------|:--------------| 58 | | `object` | (return value of `espower.defaultOptions()` but with `destructive` option is `true`) | 59 | 60 | Configuration options for `espower` module. If not passed, default options (Same as [espower.defaultOptions()](https://github.com/power-assert-js/espower#var-options--espowerdefaultoptions)) will be used, but `options.destructive` is set to `true`, and if `options.path` is falsy, `options.path` is set to value of `filepath` argument by espower-source module. 61 | 62 | 63 | #### options.ecmaVersion 64 | 65 | | type | default value | 66 | |:---------|:--------------| 67 | | `number` | `2018` | 68 | 69 | The ECMAScript version to parse and analyze. Must be either 3, 5, 6 (2015), 2016, 2017, or 2018. 70 | 71 | 72 | #### options.sourceType 73 | 74 | | type | default value | 75 | |:---------|:--------------| 76 | | `string` | `'module'` | 77 | 78 | The source type of the code. Must be either `"script"` or `"module"`. 79 | 80 | 81 | INSTALL 82 | --------------------------------------- 83 | 84 | ### via npm 85 | 86 | Install 87 | 88 | $ npm install --save-dev espower-source 89 | 90 | 91 | OUR SUPPORT POLICY 92 | --------------------------------------- 93 | 94 | We support Node under maintenance. In other words, we stop supporting old Node version when [their maintenance ends](https://github.com/nodejs/LTS). 95 | 96 | This means that any other environment is not supported. 97 | 98 | NOTE: If espower-source works in any of the unsupported environments, it is purely coincidental and has no bearing on future compatibility. Use at your own risk. 99 | 100 | 101 | AUTHOR 102 | --------------------------------------- 103 | * [Takuto Wada](https://github.com/twada) 104 | 105 | 106 | CONTRIBUTORS 107 | --------------------------------------- 108 | * [azu](https://github.com/azu) 109 | * [James Talmage (jamestalmage)](https://github.com/jamestalmage) 110 | * [Yoshiki Shibukawa (shibukawa)](https://github.com/shibukawa) 111 | * [Yiyu He (dead-horse)](https://github.com/dead-horse) 112 | * [Eward Song (shepherdwind)](https://github.com/shepherdwind) 113 | 114 | 115 | LICENSE 116 | --------------------------------------- 117 | Licensed under the [MIT](https://github.com/power-assert-js/espower-source/blob/master/MIT-LICENSE.txt) license. 118 | 119 | 120 | [npm-url]: https://npmjs.org/package/espower-source 121 | [npm-image]: https://badge.fury.io/js/espower-source.svg 122 | 123 | [travis-url]: https://travis-ci.org/power-assert-js/espower-source 124 | [travis-image]: https://secure.travis-ci.org/power-assert-js/espower-source.svg?branch=master 125 | 126 | [depstat-url]: https://gemnasium.com/power-assert-js/espower-source 127 | [depstat-image]: https://gemnasium.com/power-assert-js/espower-source.svg 128 | 129 | [license-url]: https://github.com/power-assert-js/espower-source/blob/master/MIT-LICENSE.txt 130 | [license-image]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat 131 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var gutil = require('gulp-util'); 3 | var jshint = require('gulp-jshint'); 4 | var stylish = require('jshint-stylish'); 5 | var mocha = require('gulp-mocha'); 6 | var config = { 7 | jshint: { 8 | src: './index.js' 9 | }, 10 | test: { 11 | base: './test/', 12 | pattern: '**/*test.js' 13 | } 14 | }; 15 | 16 | function runMochaSimply() { 17 | return gulp 18 | .src(config.test.base + config.test.pattern, {read: false}) 19 | .pipe(mocha({ 20 | ui: 'bdd', 21 | reporter: 'dot' 22 | })) 23 | .on('error', gutil.log); 24 | } 25 | 26 | gulp.task('watch', function () { 27 | gulp.watch(['index.js', 'test/**/*.js'], runMochaSimply); 28 | runMochaSimply(); 29 | }); 30 | 31 | gulp.task('lint', function() { 32 | return gulp.src(config.jshint.src) 33 | .pipe(jshint()) 34 | .pipe(jshint.reporter(stylish)); 35 | }); 36 | 37 | gulp.task('unit', function () { 38 | return runMochaSimply(); 39 | }); 40 | 41 | gulp.task('test', gulp.task('unit')); 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * espower-source - Power Assert instrumentor from source to source. 3 | * 4 | * https://github.com/power-assert-js/espower-source 5 | * 6 | * Copyright (c) 2014-2018 Takuto Wada 7 | * Licensed under the MIT license. 8 | * https://github.com/power-assert-js/espower-source/blob/master/MIT-LICENSE.txt 9 | */ 10 | 'use strict'; 11 | 12 | var espower = require('espower'); 13 | var acorn = require('acorn'); 14 | require('acorn-es7-plugin')(acorn); 15 | var estraverse = require('estraverse'); 16 | var mergeVisitors = require('merge-estraverse-visitors'); 17 | var empowerAssert = require('empower-assert'); 18 | var escodegen = require('escodegen'); 19 | var extend = require('xtend'); 20 | var convert = require('convert-source-map'); 21 | var transfer = require('multi-stage-sourcemap').transfer; 22 | var _path = require('path'); 23 | var isAbsolute = require('path-is-absolute'); 24 | 25 | function mergeSourceMap (incomingSourceMap, outgoingSourceMap) { 26 | if (typeof outgoingSourceMap === 'string' || outgoingSourceMap instanceof String) { 27 | outgoingSourceMap = JSON.parse(outgoingSourceMap); 28 | } 29 | if (!incomingSourceMap) { 30 | return outgoingSourceMap; 31 | } 32 | return JSON.parse(transfer({fromSourceMap: outgoingSourceMap, toSourceMap: incomingSourceMap})); 33 | } 34 | 35 | function copyPropertyIfExists (name, from, to) { 36 | if (from[name]) { 37 | to.setProperty(name, from[name]); 38 | } 39 | } 40 | 41 | function reconnectSourceMap (inMap, outMap) { 42 | var mergedRawMap = mergeSourceMap(inMap, outMap.toObject()); 43 | var reMap = convert.fromObject(mergedRawMap); 44 | copyPropertyIfExists('sources', inMap, reMap); 45 | copyPropertyIfExists('sourceRoot', inMap, reMap); 46 | copyPropertyIfExists('sourcesContent', inMap, reMap); 47 | return reMap; 48 | } 49 | 50 | function handleIncomingSourceMap (originalCode, options) { 51 | var inMap; 52 | if (options.sourceMap) { 53 | if (typeof options.sourceMap === 'string' || options.sourceMap instanceof String) { 54 | options.sourceMap = JSON.parse(options.sourceMap); 55 | } 56 | inMap = options.sourceMap; 57 | } else { 58 | var sourceMappingURL = retrieveSourceMapURL(originalCode); 59 | var commented; 60 | // relative file sourceMap 61 | // //# sourceMappingURL=foo.js.map or /*# sourceMappingURL=foo.js.map */ 62 | if (sourceMappingURL && !/^data:application\/json[^,]+base64,/.test(sourceMappingURL)) { 63 | commented = convert.fromMapFileSource(originalCode, _path.dirname(options.path)); 64 | } else { 65 | // inline sourceMap or none sourceMap 66 | commented = convert.fromSource(originalCode); 67 | } 68 | 69 | if (commented) { 70 | inMap = commented.toObject(); 71 | options.sourceMap = inMap; 72 | } 73 | } 74 | return inMap; 75 | } 76 | 77 | // copy from https://github.com/evanw/node-source-map-support/blob/master/source-map-support.js#L99 78 | function retrieveSourceMapURL(source) { 79 | // //# sourceMappingURL=foo.js.map /*# sourceMappingURL=foo.js.map */ 80 | var re = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/mg; 81 | // Keep executing the search to find the *last* sourceMappingURL to avoid 82 | // picking up sourceMappingURLs from comments, strings, etc. 83 | var lastMatch, match; 84 | while (match = re.exec(source)) { 85 | lastMatch = match; 86 | } 87 | if (!lastMatch) { 88 | return null; 89 | } 90 | return lastMatch[1]; 91 | }; 92 | 93 | 94 | function adjustFilepath (filepath, sourceRoot) { 95 | if (!sourceRoot || !isAbsolute(filepath)) { 96 | return filepath; 97 | } 98 | return _path.relative(sourceRoot, filepath); 99 | } 100 | 101 | function syntaxErrorLine(lineNumber, maxLineNumberLength, line) { 102 | var content = [' ']; 103 | var lineNumberString = String(lineNumber); 104 | for (var i = lineNumberString.length; i < maxLineNumberLength; i++) { 105 | content.push(' '); 106 | } 107 | content.push(lineNumberString, ': ', line); 108 | return content.join(''); 109 | } 110 | 111 | function showSyntaxErrorDetail(code, error, filepath) { 112 | var i; 113 | var begin = code.lastIndexOf('\n', error.pos); 114 | var end = code.indexOf('\n', error.pos); 115 | if (end === -1) { 116 | end = undefined; 117 | } 118 | var line = code.slice(begin + 1, end); 119 | var beforeLines = []; 120 | for (i = 0; i < 5; i++) { 121 | if (begin === -1) { 122 | break; 123 | } 124 | var lastBegin = begin; 125 | begin = code.lastIndexOf('\n', begin - 1); 126 | beforeLines.unshift(code.slice(begin + 1, lastBegin)); 127 | if (begin === 0) { 128 | break; 129 | } 130 | } 131 | var afterLines = []; 132 | for (i = 0; i < 5; i++) { 133 | if (end === undefined) { 134 | break; 135 | } 136 | var lastEnd = end; 137 | end = code.indexOf('\n', end + 1); 138 | if (end === -1) { 139 | end = undefined; 140 | } 141 | afterLines.push(code.slice(lastEnd + 1, end)); 142 | } 143 | 144 | var lines = ['']; 145 | var numberLength = String(error.loc.line + afterLines.length).length; 146 | for (i = 0; i < beforeLines.length; i++) { 147 | lines.push( 148 | syntaxErrorLine(error.loc.line - beforeLines.length + i, numberLength, beforeLines[i]) 149 | ); 150 | } 151 | lines.push(syntaxErrorLine(error.loc.line, numberLength, line)); 152 | var lineContent = []; 153 | for (i = 0; i < 6 + numberLength + error.loc.column - 1; i++) { 154 | lineContent.push(' '); 155 | } 156 | lineContent.push('^'); 157 | lines.push(lineContent.join('')); 158 | for (i = 0; i < afterLines.length; i++) { 159 | lines.push( 160 | syntaxErrorLine(error.loc.line + i + 1, numberLength, afterLines[i]) 161 | ); 162 | } 163 | lines.push('', 'Parse Error: ' + error.message + (filepath ? ' in ' + filepath : '')); 164 | var detail = lines.join('\n'); 165 | var err = new SyntaxError(detail); 166 | err.loc = error.loc; 167 | err.pos = error.pos; 168 | err.raisedAt = error.pos; 169 | throw err; 170 | } 171 | 172 | function instrument (originalCode, filepath, options) { 173 | var jsAst; 174 | try { 175 | jsAst = acorn.parse(originalCode, {locations: true, ecmaVersion: options.ecmaVersion, sourceType: options.sourceType, plugins: {asyncawait: true}}); 176 | } catch (e) { 177 | if (e instanceof SyntaxError && e.pos && e.loc) { 178 | showSyntaxErrorDetail(originalCode, e, filepath); 179 | } 180 | throw e; 181 | } 182 | var modifiedAst = estraverse.replace(jsAst, mergeVisitors([ 183 | { 184 | enter: empowerAssert.enter 185 | }, 186 | espower.createVisitor(jsAst, options) 187 | ])); 188 | var escodegenOptions = extend({ 189 | sourceMap: adjustFilepath(filepath || options.path, options.sourceRoot), 190 | sourceContent: originalCode, 191 | sourceMapWithCode: true 192 | }); 193 | if (options.sourceRoot) { 194 | escodegenOptions.sourceMapRoot = options.sourceRoot; 195 | } 196 | return escodegen.generate(modifiedAst, escodegenOptions); 197 | } 198 | 199 | function instrumentWithoutSourceMapOutput (originalCode, options) { 200 | var jsAst; 201 | try { 202 | jsAst = acorn.parse(originalCode, {locations: true, ecmaVersion: options.ecmaVersion, sourceType: options.sourceType, plugins: {asyncawait: true}}); 203 | } catch (e) { 204 | if (e instanceof SyntaxError && e.pos && e.loc) { 205 | showSyntaxErrorDetail(originalCode, e); 206 | } 207 | throw e; 208 | } 209 | var modifiedAst = estraverse.replace(jsAst, mergeVisitors([ 210 | { 211 | enter: empowerAssert.enter 212 | }, 213 | espower.createVisitor(jsAst, options) 214 | ])); 215 | return escodegen.generate(modifiedAst); 216 | } 217 | 218 | function mergeEspowerOptions (options, filepath) { 219 | return extend(espower.defaultOptions(), { 220 | ecmaVersion: 2018, 221 | sourceType: 'module', 222 | path: filepath 223 | }, options); 224 | } 225 | 226 | module.exports = function espowerSource (originalCode, filepath, options) { 227 | if (typeof originalCode === 'undefined' || originalCode === null) { 228 | throw new espower.EspowerError('`originalCode` is not specified', espowerSource); 229 | } 230 | var espowerOptions = mergeEspowerOptions(options, filepath); 231 | var inMap = handleIncomingSourceMap(originalCode, espowerOptions); 232 | if (!(filepath || espowerOptions.path)) { 233 | return instrumentWithoutSourceMapOutput(originalCode, espowerOptions); 234 | } 235 | var instrumented = instrument(originalCode, filepath, espowerOptions); 236 | var outMap = convert.fromJSON(instrumented.map.toString()); 237 | if (inMap) { 238 | var reMap = reconnectSourceMap(inMap, outMap); 239 | return instrumented.code + '\n' + reMap.toComment() + '\n'; 240 | } else { 241 | return instrumented.code + '\n' + outMap.toComment() + '\n'; 242 | } 243 | }; 244 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "espower-source", 3 | "description": "Power Assert instrumentor from source to source, with source-map", 4 | "version": "2.3.0", 5 | "author": { 6 | "name": "Takuto Wada", 7 | "email": "takuto.wada@gmail.com", 8 | "url": "https://github.com/twada" 9 | }, 10 | "bugs": "https://github.com/power-assert-js/espower-source/issues", 11 | "contributors": [ 12 | { 13 | "name": "azu", 14 | "url": "https://github.com/azu" 15 | }, 16 | { 17 | "name": "James Talmage", 18 | "url": "https://github.com/jamestalmage" 19 | }, 20 | { 21 | "name": "Yoshiki Shibukawa", 22 | "url": "https://github.com/shibukawa" 23 | }, 24 | { 25 | "name": "Yiyu He", 26 | "url": "https://github.com/dead-horse" 27 | }, 28 | { 29 | "name": "Eward Song", 30 | "url": "https://github.com/shepherdwind" 31 | } 32 | ], 33 | "dependencies": { 34 | "acorn": "^5.0.0", 35 | "acorn-es7-plugin": "^1.0.10", 36 | "convert-source-map": "^1.1.1", 37 | "empower-assert": "^1.0.0", 38 | "escodegen": "^1.10.0", 39 | "espower": "^2.1.1", 40 | "estraverse": "^4.0.0", 41 | "merge-estraverse-visitors": "^1.0.0", 42 | "multi-stage-sourcemap": "^0.2.1", 43 | "path-is-absolute": "^1.0.0", 44 | "xtend": "^4.0.0" 45 | }, 46 | "devDependencies": { 47 | "gulp": "^4.0.2", 48 | "gulp-jshint": "^2.0.2", 49 | "gulp-mocha": "^5.0.0", 50 | "gulp-util": "^3.0.6", 51 | "jshint": "^2.9.4", 52 | "jshint-stylish": "^2.0.1", 53 | "mocha": "^5.0.0", 54 | "source-map": "^0.5.7" 55 | }, 56 | "engines": { 57 | "node": ">=0.8.0", 58 | "npm": ">=1.2.10" 59 | }, 60 | "files": [ 61 | "CHANGELOG.md", 62 | "MIT-LICENSE.txt", 63 | "README.md", 64 | "index.js", 65 | "package.json" 66 | ], 67 | "homepage": "https://github.com/power-assert-js/espower-source", 68 | "keywords": [ 69 | "power-assert", 70 | "assert", 71 | "assertion", 72 | "test", 73 | "testing" 74 | ], 75 | "license": "MIT", 76 | "main": "./index.js", 77 | "repository": { 78 | "type": "git", 79 | "url": "git://github.com/power-assert-js/espower-source.git" 80 | }, 81 | "scripts": { 82 | "preversion": "npm test", 83 | "lint": "gulp lint", 84 | "test": "gulp test" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/expected/customized.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var _rec1 = new _PowerAssertRecorder1(); 26 | var _rec2 = new _PowerAssertRecorder1(); 27 | var _rec3 = new _PowerAssertRecorder1(); 28 | var _rec4 = new _PowerAssertRecorder1(); 29 | var empower = require('empower'), formatter = require('power-assert-formatter'), busterAssertions = require('buster-assertions'), refute = empower(busterAssertions.refute, formatter(), { 30 | targetMethods: { 31 | oneArg: ['isNull'], 32 | twoArgs: ['same'] 33 | } 34 | }), truthy = 'true', falsy = 'false'; 35 | refute(_rec1._expr(_rec1._capt(truthy, 'arguments/0'), { 36 | content: 'refute(truthy)', 37 | filepath: 'test/fixtures/customized.js', 38 | line: 7 39 | })); 40 | refute.isNull(_rec2._expr(_rec2._capt(falsy, 'arguments/0'), { 41 | content: 'refute.isNull(falsy)', 42 | filepath: 'test/fixtures/customized.js', 43 | line: 8 44 | })); 45 | refute.same(_rec3._expr(_rec3._capt(truthy, 'arguments/0'), { 46 | content: 'refute.same(truthy, falsy)', 47 | filepath: 'test/fixtures/customized.js', 48 | line: 9 49 | }), _rec4._expr(_rec4._capt(falsy, 'arguments/1'), { 50 | content: 'refute.same(truthy, falsy)', 51 | filepath: 'test/fixtures/customized.js', 52 | line: 9 53 | })); 54 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZml4dHVyZXMvY3VzdG9taXplZC5qcyJdLCJuYW1lcyI6WyJfUG93ZXJBc3NlcnRSZWNvcmRlcjEiLCJQb3dlckFzc2VydFJlY29yZGVyIiwiY2FwdHVyZWQiLCJwcm90b3R5cGUiLCJfY2FwdCIsInZhbHVlIiwiZXNwYXRoIiwicHVzaCIsIl9leHByIiwic291cmNlIiwiY2FwdHVyZWRWYWx1ZXMiLCJwb3dlckFzc2VydENvbnRleHQiLCJldmVudHMiLCJfcmVjMSIsIl9yZWMyIiwiX3JlYzMiLCJfcmVjNCIsImVtcG93ZXIiLCJyZXF1aXJlIiwiZm9ybWF0dGVyIiwiYnVzdGVyQXNzZXJ0aW9ucyIsInJlZnV0ZSIsInRhcmdldE1ldGhvZHMiLCJvbmVBcmciLCJ0d29BcmdzIiwidHJ1dGh5IiwiZmFsc3kiLCJjb250ZW50IiwiZmlsZXBhdGgiLCJsaW5lIiwiaXNOdWxsIiwic2FtZSJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBQUEscUJBQUE7QUFBQSxhQUFBQyxtQkFBQTtBQUFBLGFBQUFDLFFBQUE7QUFBQTtBQUFBLElBQUFELG1CQUFBLENBQUFFLFNBQUEsQ0FBQUMsS0FBQSxZQUFBQSxLQUFBLENBQUFDLEtBQUEsRUFBQUMsTUFBQTtBQUFBLGFBQUFKLFFBQUEsQ0FBQUssSUFBQTtBQUFBLFlBQUFGLEtBQUEsRUFBQUEsS0FBQTtBQUFBLFlBQUFDLE1BQUEsRUFBQUEsTUFBQTtBQUFBO0FBQUEsZUFBQUQsS0FBQTtBQUFBO0FBQUEsSUFBQUosbUJBQUEsQ0FBQUUsU0FBQSxDQUFBSyxLQUFBLFlBQUFBLEtBQUEsQ0FBQUgsS0FBQSxFQUFBSSxNQUFBO0FBQUEsWUFBQUMsY0FBQSxRQUFBUixRQUFBO0FBQUEsYUFBQUEsUUFBQTtBQUFBO0FBQUEsWUFBQVMsa0JBQUE7QUFBQSxnQkFBQU4sS0FBQSxFQUFBQSxLQUFBO0FBQUEsZ0JBQUFPLE1BQUEsRUFBQUYsY0FBQTtBQUFBO0FBQUEsWUFBQUQsTUFBQSxFQUFBQSxNQUFBO0FBQUE7QUFBQTtBQUFBLFdBQUFSLG1CQUFBO0FBQUE7QUFNTyxJQUFBWSxLQUFBLE9BQUFiLHFCQUFBLEdBTlA7QUFPYyxJQUFBYyxLQUFBLE9BQUFkLHFCQUFBLEdBUGQ7QUFRWSxJQUFBZSxLQUFBLE9BQUFmLHFCQUFBLEdBUlo7QUFRb0IsSUFBQWdCLEtBQUEsT0FBQWhCLHFCQUFBLEdBUnBCO0FBQUEsSUFBSWlCLE9BQUEsR0FBVUMsT0FBQSxDQUFRLFNBQVIsQ0FBZCxFQUNJQyxTQUFBLEdBQVlELE9BQUEsQ0FBUSx3QkFBUixDQURoQixFQUVJRSxnQkFBQSxHQUFtQkYsT0FBQSxDQUFRLG1CQUFSLENBRnZCLEVBR0lHLE1BQUEsR0FBU0osT0FBQSxDQUFRRyxnQkFBQSxDQUFpQkMsTUFBekIsRUFBaUNGLFNBQUEsRUFBakMsRUFBOEM7QUFBQSxRQUFFRyxhQUFBLEVBQWU7QUFBQSxZQUFFQyxNQUFBLEVBQVEsQ0FBQyxRQUFELENBQVY7QUFBQSxZQUFzQkMsT0FBQSxFQUFTLENBQUMsTUFBRCxDQUEvQjtBQUFBLFNBQWpCO0FBQUEsS0FBOUMsQ0FIYixFQUlJQyxNQUFBLEdBQVMsTUFKYixFQUtJQyxLQUFBLEdBQVEsT0FMWjtBQU1BTCxNQUFBLENBQU9SLEtBQUEsQ0FBQUwsS0FBQSxDQUFBSyxLQUFBLENBQUFULEtBQUEsQ0FBQXFCLE1BQUE7QUFBQSxJQUFBRSxPQUFBO0FBQUEsSUFBQUMsUUFBQTtBQUFBLElBQUFDLElBQUE7QUFBQSxFQUFQLEVBTkE7QUFPQVIsTUFBQSxDQUFPUyxNQUFQLENBQWNoQixLQUFBLENBQUFOLEtBQUEsQ0FBQU0sS0FBQSxDQUFBVixLQUFBLENBQUFzQixLQUFBO0FBQUEsSUFBQUMsT0FBQTtBQUFBLElBQUFDLFFBQUE7QUFBQSxJQUFBQyxJQUFBO0FBQUEsRUFBZCxFQVBBO0FBUUFSLE1BQUEsQ0FBT1UsSUFBUCxDQUFZaEIsS0FBQSxDQUFBUCxLQUFBLENBQUFPLEtBQUEsQ0FBQVgsS0FBQSxDQUFBcUIsTUFBQTtBQUFBLElBQUFFLE9BQUE7QUFBQSxJQUFBQyxRQUFBO0FBQUEsSUFBQUMsSUFBQTtBQUFBLEVBQVosRUFBb0JiLEtBQUEsQ0FBQVIsS0FBQSxDQUFBUSxLQUFBLENBQUFaLEtBQUEsQ0FBQXNCLEtBQUE7QUFBQSxJQUFBQyxPQUFBO0FBQUEsSUFBQUMsUUFBQTtBQUFBLElBQUFDLElBQUE7QUFBQSxFQUFwQiIsInNvdXJjZXNDb250ZW50IjpbInZhciBlbXBvd2VyID0gcmVxdWlyZSgnZW1wb3dlcicpLFxuICAgIGZvcm1hdHRlciA9IHJlcXVpcmUoJ3Bvd2VyLWFzc2VydC1mb3JtYXR0ZXInKSxcbiAgICBidXN0ZXJBc3NlcnRpb25zID0gcmVxdWlyZShcImJ1c3Rlci1hc3NlcnRpb25zXCIpLFxuICAgIHJlZnV0ZSA9IGVtcG93ZXIoYnVzdGVyQXNzZXJ0aW9ucy5yZWZ1dGUsIGZvcm1hdHRlcigpLCB7IHRhcmdldE1ldGhvZHM6IHsgb25lQXJnOiBbJ2lzTnVsbCddLCB0d29BcmdzOiBbJ3NhbWUnXSB9IH0pLFxuICAgIHRydXRoeSA9ICd0cnVlJyxcbiAgICBmYWxzeSA9ICdmYWxzZSc7XG5yZWZ1dGUodHJ1dGh5KTtcbnJlZnV0ZS5pc051bGwoZmFsc3kpO1xucmVmdXRlLnNhbWUodHJ1dGh5LCBmYWxzeSk7XG4iXX0= 55 | -------------------------------------------------------------------------------- /test/expected/es2018.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var _rec2 = new _PowerAssertRecorder1(); 26 | var _rec3 = new _PowerAssertRecorder1(); 27 | import assert from 'power-assert'; 28 | const urls = [ 29 | 'https://github.com/tc39/proposal-object-rest-spread', 30 | 'https://github.com/tc39/proposal-regexp-lookbehind', 31 | 'https://github.com/tc39/proposal-regexp-unicode-property-escapes', 32 | 'https://github.com/tc39/proposal-promise-finally', 33 | 'https://github.com/tc39/proposal-async-iteration' 34 | ]; 35 | async function* ait() { 36 | for (const url of urls) { 37 | console.log(`Fetching: ${ url }`); 38 | const response = await fetch(url); 39 | const iterable = response.text(); 40 | yield iterable; 41 | } 42 | } 43 | async function b() { 44 | var _rec1 = new _PowerAssertRecorder1(); 45 | for await (const x of ait()) { 46 | const title = x.match(/(.+)<\/title>/)[1]; 47 | assert(_rec1._expr(_rec1._capt(title, 'arguments/0'), { 48 | content: 'assert(title)', 49 | filepath: 'test/fixtures/es2018.js', 50 | line: 23, 51 | async: true 52 | })); 53 | } 54 | } 55 | b(); 56 | const obj = { 57 | a: 1, 58 | b: 2 59 | }; 60 | assert.deepStrictEqual(_rec2._expr(_rec2._capt({ 61 | ..._rec2._capt(obj, 'arguments/0/properties/0/argument'), 62 | c: 3 63 | }, 'arguments/0'), { 64 | content: 'assert.deepStrictEqual({...obj,c: 3}, {a: 1,b: 2,c: 3})', 65 | filepath: 'test/fixtures/es2018.js', 66 | line: 30 67 | }), _rec3._expr(_rec3._capt({ 68 | a: 1, 69 | b: 2, 70 | c: 3 71 | }, 'arguments/1'), { 72 | content: 'assert.deepStrictEqual({...obj,c: 3}, {a: 1,b: 2,c: 3})', 73 | filepath: 'test/fixtures/es2018.js', 74 | line: 30 75 | })); 76 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZml4dHVyZXMvZXMyMDE4LmpzIl0sIm5hbWVzIjpbIl9Qb3dlckFzc2VydFJlY29yZGVyMSIsIlBvd2VyQXNzZXJ0UmVjb3JkZXIiLCJjYXB0dXJlZCIsInByb3RvdHlwZSIsIl9jYXB0IiwidmFsdWUiLCJlc3BhdGgiLCJwdXNoIiwiX2V4cHIiLCJzb3VyY2UiLCJjYXB0dXJlZFZhbHVlcyIsInBvd2VyQXNzZXJ0Q29udGV4dCIsImV2ZW50cyIsIl9yZWMyIiwiX3JlYzMiLCJhc3NlcnQiLCJ1cmxzIiwiYWl0IiwidXJsIiwiY29uc29sZSIsImxvZyIsInJlc3BvbnNlIiwiZmV0Y2giLCJpdGVyYWJsZSIsInRleHQiLCJiIiwiX3JlYzEiLCJ4IiwidGl0bGUiLCJtYXRjaCIsImNvbnRlbnQiLCJmaWxlcGF0aCIsImxpbmUiLCJhc3luYyIsIm9iaiIsImEiLCJkZWVwU3RyaWN0RXF1YWwiLCJjIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFBQSxxQkFBQTtBQUFBLGFBQUFDLG1CQUFBO0FBQUEsYUFBQUMsUUFBQTtBQUFBO0FBQUEsSUFBQUQsbUJBQUEsQ0FBQUUsU0FBQSxDQUFBQyxLQUFBLFlBQUFBLEtBQUEsQ0FBQUMsS0FBQSxFQUFBQyxNQUFBO0FBQUEsYUFBQUosUUFBQSxDQUFBSyxJQUFBO0FBQUEsWUFBQUYsS0FBQSxFQUFBQSxLQUFBO0FBQUEsWUFBQUMsTUFBQSxFQUFBQSxNQUFBO0FBQUE7QUFBQSxlQUFBRCxLQUFBO0FBQUE7QUFBQSxJQUFBSixtQkFBQSxDQUFBRSxTQUFBLENBQUFLLEtBQUEsWUFBQUEsS0FBQSxDQUFBSCxLQUFBLEVBQUFJLE1BQUE7QUFBQSxZQUFBQyxjQUFBLFFBQUFSLFFBQUE7QUFBQSxhQUFBQSxRQUFBO0FBQUE7QUFBQSxZQUFBUyxrQkFBQTtBQUFBLGdCQUFBTixLQUFBLEVBQUFBLEtBQUE7QUFBQSxnQkFBQU8sTUFBQSxFQUFBRixjQUFBO0FBQUE7QUFBQSxZQUFBRCxNQUFBLEVBQUFBLE1BQUE7QUFBQTtBQUFBO0FBQUEsV0FBQVIsbUJBQUE7QUFBQTtBQTZCdUIsSUFBQVksS0FBQSxPQUFBYixxQkFBQSxHQTdCdkI7QUE2QnlDLElBQUFjLEtBQUEsT0FBQWQscUJBQUEsR0E3QnpDO0FBQUEsT0FBT2UsTUFBUCxNQUFtQixjQUFuQjtBQUVBLE1BQU1DLElBQUEsR0FBTztBQUFBLElBQ1QscURBRFM7QUFBQSxJQUVULG9EQUZTO0FBQUEsSUFHVCxrRUFIUztBQUFBLElBSVQsa0RBSlM7QUFBQSxJQUtULGtEQUxTO0FBQUEsQ0FBYixDQUZBO0FBVUEsZ0JBQWlCQyxHQUFqQixHQUF3QjtBQUFBLElBQ3BCLFdBQVdDLEdBQVgsSUFBa0JGLElBQWxCLEVBQXdCO0FBQUEsUUFDcEJHLE9BQUEsQ0FBUUMsR0FBUixDQUFZLENBQUMsVUFBRCxHQUFhRixHQUFiLEdBQVosRUFEb0I7QUFBQSxRQUVwQixNQUFNRyxRQUFBLEdBQVcsTUFBTUMsS0FBQSxDQUFNSixHQUFOLENBQXZCLENBRm9CO0FBQUEsUUFHcEIsTUFBTUssUUFBQSxHQUFXRixRQUFBLENBQVNHLElBQVQsRUFBakIsQ0FIb0I7QUFBQSxRQUlwQixNQUFNRCxRQUFOLENBSm9CO0FBQUEsS0FESjtBQUFBLENBVnhCO0FBbUJBLGVBQWVFLENBQWYsR0FBb0I7QUFBQSxJQUdMLElBQUFDLEtBQUEsT0FBQTFCLHFCQUFBLEdBSEs7QUFBQSxJQUNoQixpQkFBaUIyQixDQUFqQixJQUFzQlYsR0FBQSxFQUF0QixFQUE2QjtBQUFBLFFBQ3pCLE1BQU1XLEtBQUEsR0FBUUQsQ0FBQSxDQUFFRSxLQUFGLENBQVEsc0JBQVIsRUFBZ0MsQ0FBaEMsQ0FBZCxDQUR5QjtBQUFBLFFBRXpCZCxNQUFBLENBQU9XLEtBQUEsQ0FBQWxCLEtBQUEsQ0FBQWtCLEtBQUEsQ0FBQXRCLEtBQUEsQ0FBQXdCLEtBQUE7QUFBQSxZQUFBRSxPQUFBO0FBQUEsWUFBQUMsUUFBQTtBQUFBLFlBQUFDLElBQUE7QUFBQSxZQUFBQyxLQUFBO0FBQUEsVUFBUCxFQUZ5QjtBQUFBLEtBRGI7QUFBQSxDQW5CcEI7QUEwQkFSLENBQUEsR0ExQkE7QUE0QkEsTUFBTVMsR0FBQSxHQUFNO0FBQUEsSUFBRUMsQ0FBQSxFQUFHLENBQUw7QUFBQSxJQUFRVixDQUFBLEVBQUcsQ0FBWDtBQUFBLENBQVosQ0E1QkE7QUE2QkFWLE1BQUEsQ0FBT3FCLGVBQVAsQ0FBdUJ2QixLQUFBLENBQUFMLEtBQUEsQ0FBQUssS0FBQSxDQUFBVCxLQUFBO0FBQUEsSUFBRSxHQUFGUyxLQUFLLENBQUFULEtBQUEsQ0FBQThCLEdBQUEsc0NBQUw7QUFBQSxJQUFVRyxDQUFBLEVBQUcsQ0FBYjtBQUFBO0FBQUEsSUFBQVAsT0FBQTtBQUFBLElBQUFDLFFBQUE7QUFBQSxJQUFBQyxJQUFBO0FBQUEsRUFBdkIsRUFBeUNsQixLQUFBLENBQUFOLEtBQUEsQ0FBQU0sS0FBQSxDQUFBVixLQUFBO0FBQUEsSUFBRStCLENBQUEsRUFBRyxDQUFMO0FBQUEsSUFBUVYsQ0FBQSxFQUFHLENBQVg7QUFBQSxJQUFjWSxDQUFBLEVBQUcsQ0FBakI7QUFBQTtBQUFBLElBQUFQLE9BQUE7QUFBQSxJQUFBQyxRQUFBO0FBQUEsSUFBQUMsSUFBQTtBQUFBLEVBQXpDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5jb25zdCB1cmxzID0gW1xuICAgICdodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1vYmplY3QtcmVzdC1zcHJlYWQnLFxuICAgICdodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1yZWdleHAtbG9va2JlaGluZCcsXG4gICAgJ2h0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXJlZ2V4cC11bmljb2RlLXByb3BlcnR5LWVzY2FwZXMnLFxuICAgICdodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1wcm9taXNlLWZpbmFsbHknLFxuICAgICdodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1hc3luYy1pdGVyYXRpb24nXG5dO1xuXG5hc3luYyBmdW5jdGlvbiAqIGFpdCAoKSB7XG4gICAgZm9yIChjb25zdCB1cmwgb2YgdXJscykge1xuICAgICAgICBjb25zb2xlLmxvZyhgRmV0Y2hpbmc6ICR7dXJsfWApO1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCk7XG4gICAgICAgIGNvbnN0IGl0ZXJhYmxlID0gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICB5aWVsZCBpdGVyYWJsZTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGIgKCkge1xuICAgIGZvciBhd2FpdCAoY29uc3QgeCBvZiBhaXQoKSkge1xuICAgICAgICBjb25zdCB0aXRsZSA9IHgubWF0Y2goLzx0aXRsZT4oLispPFxcL3RpdGxlPi8pWzFdO1xuICAgICAgICBhc3NlcnQodGl0bGUpO1xuICAgIH1cbn1cblxuYigpO1xuXG5jb25zdCBvYmogPSB7IGE6IDEsIGI6IDIgfTtcbmFzc2VydC5kZWVwU3RyaWN0RXF1YWwoeyAuLi5vYmosIGM6IDMgfSwgeyBhOiAxLCBiOiAyLCBjOiAzIH0pO1xuIl19 77 | -------------------------------------------------------------------------------- /test/expected/example.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var _rec1 = new _PowerAssertRecorder1(); 26 | var _rec2 = new _PowerAssertRecorder1(); 27 | var _rec3 = new _PowerAssertRecorder1(); 28 | var assert = require('power-assert'), truthy = 'true', falsy = 'false'; 29 | assert(_rec1._expr(_rec1._capt(falsy, 'arguments/0'), { 30 | content: 'assert(falsy)', 31 | filepath: 'test/fixtures/example.js', 32 | line: 4 33 | })); 34 | assert.equal(_rec2._expr(_rec2._capt(truthy, 'arguments/0'), { 35 | content: 'assert.equal(truthy, falsy)', 36 | filepath: 'test/fixtures/example.js', 37 | line: 5 38 | }), _rec3._expr(_rec3._capt(falsy, 'arguments/1'), { 39 | content: 'assert.equal(truthy, falsy)', 40 | filepath: 'test/fixtures/example.js', 41 | line: 5 42 | })); 43 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZml4dHVyZXMvZXhhbXBsZS5qcyJdLCJuYW1lcyI6WyJfUG93ZXJBc3NlcnRSZWNvcmRlcjEiLCJQb3dlckFzc2VydFJlY29yZGVyIiwiY2FwdHVyZWQiLCJwcm90b3R5cGUiLCJfY2FwdCIsInZhbHVlIiwiZXNwYXRoIiwicHVzaCIsIl9leHByIiwic291cmNlIiwiY2FwdHVyZWRWYWx1ZXMiLCJwb3dlckFzc2VydENvbnRleHQiLCJldmVudHMiLCJfcmVjMSIsIl9yZWMyIiwiX3JlYzMiLCJhc3NlcnQiLCJyZXF1aXJlIiwidHJ1dGh5IiwiZmFsc3kiLCJjb250ZW50IiwiZmlsZXBhdGgiLCJsaW5lIiwiZXF1YWwiXSwibWFwcGluZ3MiOiJBQUFBLElBQUFBLHFCQUFBO0FBQUEsYUFBQUMsbUJBQUE7QUFBQSxhQUFBQyxRQUFBO0FBQUE7QUFBQSxJQUFBRCxtQkFBQSxDQUFBRSxTQUFBLENBQUFDLEtBQUEsWUFBQUEsS0FBQSxDQUFBQyxLQUFBLEVBQUFDLE1BQUE7QUFBQSxhQUFBSixRQUFBLENBQUFLLElBQUE7QUFBQSxZQUFBRixLQUFBLEVBQUFBLEtBQUE7QUFBQSxZQUFBQyxNQUFBLEVBQUFBLE1BQUE7QUFBQTtBQUFBLGVBQUFELEtBQUE7QUFBQTtBQUFBLElBQUFKLG1CQUFBLENBQUFFLFNBQUEsQ0FBQUssS0FBQSxZQUFBQSxLQUFBLENBQUFILEtBQUEsRUFBQUksTUFBQTtBQUFBLFlBQUFDLGNBQUEsUUFBQVIsUUFBQTtBQUFBLGFBQUFBLFFBQUE7QUFBQTtBQUFBLFlBQUFTLGtCQUFBO0FBQUEsZ0JBQUFOLEtBQUEsRUFBQUEsS0FBQTtBQUFBLGdCQUFBTyxNQUFBLEVBQUFGLGNBQUE7QUFBQTtBQUFBLFlBQUFELE1BQUEsRUFBQUEsTUFBQTtBQUFBO0FBQUE7QUFBQSxXQUFBUixtQkFBQTtBQUFBO0FBR08sSUFBQVksS0FBQSxPQUFBYixxQkFBQSxHQUhQO0FBSWEsSUFBQWMsS0FBQSxPQUFBZCxxQkFBQSxHQUpiO0FBSXFCLElBQUFlLEtBQUEsT0FBQWYscUJBQUEsR0FKckI7QUFBQSxJQUFJZ0IsTUFBQSxHQUFTQyxPQUFBLENBQVEsY0FBUixDQUFiLEVBQ0lDLE1BQUEsR0FBUyxNQURiLEVBRUlDLEtBQUEsR0FBUSxPQUZaO0FBR0FILE1BQUEsQ0FBT0gsS0FBQSxDQUFBTCxLQUFBLENBQUFLLEtBQUEsQ0FBQVQsS0FBQSxDQUFBZSxLQUFBO0FBQUEsSUFBQUMsT0FBQTtBQUFBLElBQUFDLFFBQUE7QUFBQSxJQUFBQyxJQUFBO0FBQUEsRUFBUCxFQUhBO0FBSUFOLE1BQUEsQ0FBT08sS0FBUCxDQUFhVCxLQUFBLENBQUFOLEtBQUEsQ0FBQU0sS0FBQSxDQUFBVixLQUFBLENBQUFjLE1BQUE7QUFBQSxJQUFBRSxPQUFBO0FBQUEsSUFBQUMsUUFBQTtBQUFBLElBQUFDLElBQUE7QUFBQSxFQUFiLEVBQXFCUCxLQUFBLENBQUFQLEtBQUEsQ0FBQU8sS0FBQSxDQUFBWCxLQUFBLENBQUFlLEtBQUE7QUFBQSxJQUFBQyxPQUFBO0FBQUEsSUFBQUMsUUFBQTtBQUFBLElBQUFDLElBQUE7QUFBQSxFQUFyQiIsInNvdXJjZXNDb250ZW50IjpbInZhciBhc3NlcnQgPSByZXF1aXJlKCdhc3NlcnQnKSxcbiAgICB0cnV0aHkgPSAndHJ1ZScsXG4gICAgZmFsc3kgPSAnZmFsc2UnO1xuYXNzZXJ0KGZhbHN5KTtcbmFzc2VydC5lcXVhbCh0cnV0aHksIGZhbHN5KTtcbiJdfQ== 44 | -------------------------------------------------------------------------------- /test/expected/example_without_filepath_and_sourcemap.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var _rec1 = new _PowerAssertRecorder1(); 26 | var _rec2 = new _PowerAssertRecorder1(); 27 | var _rec3 = new _PowerAssertRecorder1(); 28 | var assert = require('power-assert'), truthy = 'true', falsy = 'false'; 29 | assert(_rec1._expr(_rec1._capt(falsy, 'arguments/0'), { 30 | content: 'assert(falsy)', 31 | line: 4 32 | })); 33 | assert.equal(_rec2._expr(_rec2._capt(truthy, 'arguments/0'), { 34 | content: 'assert.equal(truthy, falsy)', 35 | line: 5 36 | }), _rec3._expr(_rec3._capt(falsy, 'arguments/1'), { 37 | content: 'assert.equal(truthy, falsy)', 38 | line: 5 39 | })); 40 | -------------------------------------------------------------------------------- /test/expected/with-file-sourcemap.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var Person, assert; 26 | assert = require('power-assert'); 27 | Person = function () { 28 | function Person(name, age) { 29 | this.name = name; 30 | this.age = age; 31 | } 32 | return Person; 33 | }(); 34 | describe('various types', function () { 35 | beforeEach(function () { 36 | return this.types = [ 37 | 'string', 38 | 98.6, 39 | true, 40 | false, 41 | null, 42 | undefined, 43 | [ 44 | 'nested', 45 | 'array' 46 | ], 47 | { object: true }, 48 | NaN, 49 | Infinity, 50 | /^not/, 51 | new Person('alice', 3) 52 | ]; 53 | }); 54 | return it('demo', function () { 55 | var _rec1 = new _PowerAssertRecorder1(); 56 | var bob, index; 57 | index = this.types.length - 1; 58 | bob = new Person('bob', 5); 59 | return assert(_rec1._expr(_rec1._capt(_rec1._capt(_rec1._capt(_rec1._capt(this.types, 'arguments/0/left/object/object')[_rec1._capt(index, 'arguments/0/left/object/property')], 'arguments/0/left/object').name, 'arguments/0/left') === _rec1._capt(_rec1._capt(bob, 'arguments/0/right/object').name, 'arguments/0/right'), 'arguments/0'), { 60 | content: 'assert(this.types[index].name === bob.name)', 61 | filepath: 'with-file-sourcemap.coffee', 62 | line: 33 63 | })); 64 | }); 65 | }); 66 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndpdGgtZmlsZS1zb3VyY2VtYXAuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQUEscUJBQUE7QUFBQSxhQUFBLG1CQUFBO0FBQUEsYUFBQSxRQUFBO0FBQUE7QUFBQSxJQUFBLG1CQUFBLENBQUEsU0FBQSxDQUFBLEtBQUEsWUFBQSxLQUFBLENBQUEsS0FBQSxFQUFBLE1BQUE7QUFBQSxhQUFBLFFBQUEsQ0FBQSxJQUFBO0FBQUEsWUFBQSxLQUFBLEVBQUEsS0FBQTtBQUFBLFlBQUEsTUFBQSxFQUFBLE1BQUE7QUFBQTtBQUFBLGVBQUEsS0FBQTtBQUFBO0FBQUEsSUFBQSxtQkFBQSxDQUFBLFNBQUEsQ0FBQSxLQUFBLFlBQUEsS0FBQSxDQUFBLEtBQUEsRUFBQSxNQUFBO0FBQUEsWUFBQSxjQUFBLFFBQUEsUUFBQTtBQUFBLGFBQUEsUUFBQTtBQUFBO0FBQUEsWUFBQSxrQkFBQTtBQUFBLGdCQUFBLEtBQUEsRUFBQSxLQUFBO0FBQUEsZ0JBQUEsTUFBQSxFQUFBLGNBQUE7QUFBQTtBQUFBLFlBQUEsTUFBQSxFQUFBLE1BQUE7QUFBQTtBQUFBO0FBQUEsV0FBQSxtQkFBQTtBQUFBO0FBQUEsSUFBQSxNQUFBLEVBQUEsTUFBQTtBQUFBLE1BQUEsR0FBUyxPQUFBLENBQVEsY0FBUixDQUFULENBQUE7QUFBQSxNQUFBLEdBQUEsWUFBQTtBQUFBLElBR2UsU0FBQSxNQUFBLENBQUMsSUFBRCxFQUFPLEdBQVAsRUFBQTtBQUFBLFFBQ1gsS0FBQyxJQUFELEdBQVEsSUFBUixDQURXO0FBQUEsUUFFWCxLQUFDLEdBQUQsR0FBTyxHQUFQLENBRlc7QUFBQSxLQUhmO0FBQUEsa0JBQUE7QUFBQSxDQUFBLEVBQUEsQ0FBQTtBQUFBLFFBQUEsQ0FPUyxlQVBULEVBTzBCLFlBQUE7QUFBQSxJQUN4QixVQUFBLENBQVcsWUFBQTtBQUFBLGVBQ1QsS0FBQyxLQUFELEdBQVM7QUFBQSxZQUNQLFFBRE87QUFBQSxZQUVQLElBRk87QUFBQSxZQUdQLElBSE87QUFBQSxZQUlQLEtBSk87QUFBQSxZQUtQLElBTE87QUFBQSxZQU1QLFNBTk87QUFBQSxZQU9QO0FBQUEsZ0JBQ0UsUUFERjtBQUFBLGdCQUVFLE9BRkY7QUFBQSxhQVBPO0FBQUEsWUFXUCxFQUNFLE1BQUEsRUFBUSxJQURWLEVBWE87QUFBQSxZQWNQLEdBZE87QUFBQSxZQWVQLFFBZk87QUFBQSxZQWdCUCxNQWhCTztBQUFBLFlBaUJILElBQUEsTUFBQSxDQUFPLE9BQVAsRUFBZ0IsQ0FBaEIsQ0FqQkc7QUFBQSxVQURBO0FBQUEsS0FBWCxFQUR3QjtBQUFBLFdBc0J4QixFQUFBLENBQUcsTUFBSCxFQUFXLFlBQUE7QUFBQSxRQUdGLElBQUEsS0FBQSxPQUFBLHFCQUFBLEdBSEU7QUFBQSxRQUNULElBQUEsR0FBQSxFQUFBLEtBQUEsQ0FEUztBQUFBLFFBQ1QsS0FBQSxHQUFRLEtBQUMsS0FBRCxDQUFPLE1BQVAsR0FBZ0IsQ0FBeEIsQ0FEUztBQUFBLFFBRVQsR0FBQSxHQUFVLElBQUEsTUFBQSxDQUFPLEtBQVAsRUFBYyxDQUFkLENBQVYsQ0FGUztBQUFBLGVBR1QsTUFBQSxDQUFPLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxDQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxDQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxDQUFBLEtBQUEsTUFBQyxLQUFELG9DQUFBLEtBQU8sQ0FBQSxLQUFBLENBQUEsS0FBQSxxQ0FBUCw4QkFBYyxJQUFkLDBCQUFBLEtBQXNCLENBQUEsS0FBQSxDQUF0QixLQUFzQixDQUFBLEtBQUEsQ0FBQSxHQUFBLDhCQUFJLElBQUosc0JBQXRCO0FBQUEsWUFBQSxPQUFBO0FBQUEsWUFBQSxRQUFBO0FBQUEsWUFBQSxJQUFBO0FBQUEsVUFBUCxFQUhTO0FBQUEsS0FBWCxFQXRCd0I7QUFBQSxDQVAxQiIsInNvdXJjZXNDb250ZW50IjpbImFzc2VydCA9IHJlcXVpcmUgJ3Bvd2VyLWFzc2VydCdcblxuY2xhc3MgUGVyc29uXG4gIGNvbnN0cnVjdG9yOiAobmFtZSwgYWdlKSAtPlxuICAgIEBuYW1lID0gbmFtZVxuICAgIEBhZ2UgPSBhZ2VcblxuZGVzY3JpYmUgXCJ2YXJpb3VzIHR5cGVzXCIsIC0+XG4gIGJlZm9yZUVhY2ggLT5cbiAgICBAdHlwZXMgPSBbXG4gICAgICBcInN0cmluZ1wiXG4gICAgICA5OC42XG4gICAgICB0cnVlXG4gICAgICBmYWxzZVxuICAgICAgbnVsbFxuICAgICAgYHVuZGVmaW5lZGBcbiAgICAgIFtcbiAgICAgICAgXCJuZXN0ZWRcIlxuICAgICAgICBcImFycmF5XCJcbiAgICAgIF1cbiAgICAgIHtcbiAgICAgICAgb2JqZWN0OiB0cnVlXG4gICAgICB9XG4gICAgICBOYU5cbiAgICAgIEluZmluaXR5XG4gICAgICAvXm5vdC9cbiAgICAgIG5ldyBQZXJzb24oXCJhbGljZVwiLCAzKVxuICAgIF1cblxuICBpdCBcImRlbW9cIiwgLT5cbiAgICBpbmRleCA9IEB0eXBlcy5sZW5ndGggLSAxXG4gICAgYm9iID0gbmV3IFBlcnNvbihcImJvYlwiLCA1KVxuICAgIGFzc2VydCBAdHlwZXNbaW5kZXhdLm5hbWUgaXMgYm9iLm5hbWVcbiJdfQ== 67 | -------------------------------------------------------------------------------- /test/expected/with-sourcemap.js: -------------------------------------------------------------------------------- 1 | var _PowerAssertRecorder1 = function () { 2 | function PowerAssertRecorder() { 3 | this.captured = []; 4 | } 5 | PowerAssertRecorder.prototype._capt = function _capt(value, espath) { 6 | this.captured.push({ 7 | value: value, 8 | espath: espath 9 | }); 10 | return value; 11 | }; 12 | PowerAssertRecorder.prototype._expr = function _expr(value, source) { 13 | var capturedValues = this.captured; 14 | this.captured = []; 15 | return { 16 | powerAssertContext: { 17 | value: value, 18 | events: capturedValues 19 | }, 20 | source: source 21 | }; 22 | }; 23 | return PowerAssertRecorder; 24 | }(); 25 | var Person, assert; 26 | assert = require('power-assert'); 27 | Person = function () { 28 | function Person(name, age) { 29 | this.name = name; 30 | this.age = age; 31 | } 32 | return Person; 33 | }(); 34 | describe('various types', function () { 35 | beforeEach(function () { 36 | return this.types = [ 37 | 'string', 38 | 98.6, 39 | true, 40 | false, 41 | null, 42 | undefined, 43 | [ 44 | 'nested', 45 | 'array' 46 | ], 47 | { object: true }, 48 | NaN, 49 | Infinity, 50 | /^not/, 51 | new Person('alice', 3) 52 | ]; 53 | }); 54 | return it('demo', function () { 55 | var _rec1 = new _PowerAssertRecorder1(); 56 | var bob, index; 57 | index = this.types.length - 1; 58 | bob = new Person('bob', 5); 59 | return assert(_rec1._expr(_rec1._capt(_rec1._capt(_rec1._capt(_rec1._capt(this.types, 'arguments/0/left/object/object')[_rec1._capt(index, 'arguments/0/left/object/property')], 'arguments/0/left/object').name, 'arguments/0/left') === _rec1._capt(_rec1._capt(bob, 'arguments/0/right/object').name, 'arguments/0/right'), 'arguments/0'), { 60 | content: 'assert(this.types[index].name === bob.name)', 61 | filepath: 'coffee_script_test.coffee', 62 | line: 33 63 | })); 64 | }); 65 | }); 66 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9hYnNvbHV0ZS9wYXRoL3RvL2NvZmZlZV9zY3JpcHRfdGVzdC5jb2ZmZWUiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsSUFBQSxxQkFBQTtBQUFBLGFBQUEsbUJBQUE7QUFBQSxhQUFBLFFBQUE7QUFBQTtBQUFBLElBQUEsbUJBQUEsQ0FBQSxTQUFBLENBQUEsS0FBQSxZQUFBLEtBQUEsQ0FBQSxLQUFBLEVBQUEsTUFBQTtBQUFBLGFBQUEsUUFBQSxDQUFBLElBQUE7QUFBQSxZQUFBLEtBQUEsRUFBQSxLQUFBO0FBQUEsWUFBQSxNQUFBLEVBQUEsTUFBQTtBQUFBO0FBQUEsZUFBQSxLQUFBO0FBQUE7QUFBQSxJQUFBLG1CQUFBLENBQUEsU0FBQSxDQUFBLEtBQUEsWUFBQSxLQUFBLENBQUEsS0FBQSxFQUFBLE1BQUE7QUFBQSxZQUFBLGNBQUEsUUFBQSxRQUFBO0FBQUEsYUFBQSxRQUFBO0FBQUE7QUFBQSxZQUFBLGtCQUFBO0FBQUEsZ0JBQUEsS0FBQSxFQUFBLEtBQUE7QUFBQSxnQkFBQSxNQUFBLEVBQUEsY0FBQTtBQUFBO0FBQUEsWUFBQSxNQUFBLEVBQUEsTUFBQTtBQUFBO0FBQUE7QUFBQSxXQUFBLG1CQUFBO0FBQUE7QUFBQSxJQUFBLE1BQUEsRUFBQSxNQUFBO0FBQUEsTUFBQSxHQUFTLE9BQUEsQ0FBUSxjQUFSLENBQVQsQ0FBQTtBQUFBLE1BQUEsR0FBQSxZQUFBO0FBQUEsSUFHZSxTQUFBLE1BQUEsQ0FBQyxJQUFELEVBQU8sR0FBUCxFQUFBO0FBQUEsUUFDWCxLQUFDLElBQUQsR0FBUSxJQUFSLENBRFc7QUFBQSxRQUVYLEtBQUMsR0FBRCxHQUFPLEdBQVAsQ0FGVztBQUFBLEtBSGY7QUFBQSxrQkFBQTtBQUFBLENBQUEsRUFBQSxDQUFBO0FBQUEsUUFBQSxDQU9TLGVBUFQsRUFPMEIsWUFBQTtBQUFBLElBQ3hCLFVBQUEsQ0FBVyxZQUFBO0FBQUEsZUFDVCxLQUFDLEtBQUQsR0FBUztBQUFBLFlBQ1AsUUFETztBQUFBLFlBRVAsSUFGTztBQUFBLFlBR1AsSUFITztBQUFBLFlBSVAsS0FKTztBQUFBLFlBS1AsSUFMTztBQUFBLFlBTVAsU0FOTztBQUFBLFlBT1A7QUFBQSxnQkFDRSxRQURGO0FBQUEsZ0JBRUUsT0FGRjtBQUFBLGFBUE87QUFBQSxZQVdQLEVBQ0UsTUFBQSxFQUFRLElBRFYsRUFYTztBQUFBLFlBY1AsR0FkTztBQUFBLFlBZVAsUUFmTztBQUFBLFlBZ0JQLE1BaEJPO0FBQUEsWUFpQkgsSUFBQSxNQUFBLENBQU8sT0FBUCxFQUFnQixDQUFoQixDQWpCRztBQUFBLFVBREE7QUFBQSxLQUFYLEVBRHdCO0FBQUEsV0FzQnhCLEVBQUEsQ0FBRyxNQUFILEVBQVcsWUFBQTtBQUFBLFFBR0YsSUFBQSxLQUFBLE9BQUEscUJBQUEsR0FIRTtBQUFBLFFBQ1QsSUFBQSxHQUFBLEVBQUEsS0FBQSxDQURTO0FBQUEsUUFDVCxLQUFBLEdBQVEsS0FBQyxLQUFELENBQU8sTUFBUCxHQUFnQixDQUF4QixDQURTO0FBQUEsUUFFVCxHQUFBLEdBQVUsSUFBQSxNQUFBLENBQU8sS0FBUCxFQUFjLENBQWQsQ0FBVixDQUZTO0FBQUEsZUFHVCxNQUFBLENBQU8sS0FBQSxDQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxDQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxDQUFBLEtBQUEsQ0FBQSxLQUFBLENBQUEsS0FBQSxNQUFDLEtBQUQsb0NBQUEsS0FBTyxDQUFBLEtBQUEsQ0FBQSxLQUFBLHFDQUFQLDhCQUFjLElBQWQsMEJBQUEsS0FBc0IsQ0FBQSxLQUFBLENBQXRCLEtBQXNCLENBQUEsS0FBQSxDQUFBLEdBQUEsOEJBQUksSUFBSixzQkFBdEI7QUFBQSxZQUFBLE9BQUE7QUFBQSxZQUFBLFFBQUE7QUFBQSxZQUFBLElBQUE7QUFBQSxVQUFQLEVBSFM7QUFBQSxLQUFYLEVBdEJ3QjtBQUFBLENBUDFCIiwic291cmNlc0NvbnRlbnQiOlsiYXNzZXJ0ID0gcmVxdWlyZSAncG93ZXItYXNzZXJ0J1xuXG5jbGFzcyBQZXJzb25cbiAgY29uc3RydWN0b3I6IChuYW1lLCBhZ2UpIC0+XG4gICAgQG5hbWUgPSBuYW1lXG4gICAgQGFnZSA9IGFnZVxuXG5kZXNjcmliZSBcInZhcmlvdXMgdHlwZXNcIiwgLT5cbiAgYmVmb3JlRWFjaCAtPlxuICAgIEB0eXBlcyA9IFtcbiAgICAgIFwic3RyaW5nXCJcbiAgICAgIDk4LjZcbiAgICAgIHRydWVcbiAgICAgIGZhbHNlXG4gICAgICBudWxsXG4gICAgICBgdW5kZWZpbmVkYFxuICAgICAgW1xuICAgICAgICBcIm5lc3RlZFwiXG4gICAgICAgIFwiYXJyYXlcIlxuICAgICAgXVxuICAgICAge1xuICAgICAgICBvYmplY3Q6IHRydWVcbiAgICAgIH1cbiAgICAgIE5hTlxuICAgICAgSW5maW5pdHlcbiAgICAgIC9ebm90L1xuICAgICAgbmV3IFBlcnNvbihcImFsaWNlXCIsIDMpXG4gICAgXVxuXG4gIGl0IFwiZGVtb1wiLCAtPlxuICAgIGluZGV4ID0gQHR5cGVzLmxlbmd0aCAtIDFcbiAgICBib2IgPSBuZXcgUGVyc29uKFwiYm9iXCIsIDUpXG4gICAgYXNzZXJ0IEB0eXBlc1tpbmRleF0ubmFtZSBpcyBib2IubmFtZVxuIl19 67 | -------------------------------------------------------------------------------- /test/fixtures/customized.js: -------------------------------------------------------------------------------- 1 | var empower = require('empower'), 2 | formatter = require('power-assert-formatter'), 3 | busterAssertions = require("buster-assertions"), 4 | refute = empower(busterAssertions.refute, formatter(), { targetMethods: { oneArg: ['isNull'], twoArgs: ['same'] } }), 5 | truthy = 'true', 6 | falsy = 'false'; 7 | refute(truthy); 8 | refute.isNull(falsy); 9 | refute.same(truthy, falsy); 10 | -------------------------------------------------------------------------------- /test/fixtures/es2018.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | const urls = [ 4 | 'https://github.com/tc39/proposal-object-rest-spread', 5 | 'https://github.com/tc39/proposal-regexp-lookbehind', 6 | 'https://github.com/tc39/proposal-regexp-unicode-property-escapes', 7 | 'https://github.com/tc39/proposal-promise-finally', 8 | 'https://github.com/tc39/proposal-async-iteration' 9 | ]; 10 | 11 | async function * ait () { 12 | for (const url of urls) { 13 | console.log(`Fetching: ${url}`); 14 | const response = await fetch(url); 15 | const iterable = response.text(); 16 | yield iterable; 17 | } 18 | } 19 | 20 | async function b () { 21 | for await (const x of ait()) { 22 | const title = x.match(/<title>(.+)<\/title>/)[1]; 23 | assert(title); 24 | } 25 | } 26 | 27 | b(); 28 | 29 | const obj = { a: 1, b: 2 }; 30 | assert.deepStrictEqual({ ...obj, c: 3 }, { a: 1, b: 2, c: 3 }); 31 | -------------------------------------------------------------------------------- /test/fixtures/example.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'), 2 | truthy = 'true', 3 | falsy = 'false'; 4 | assert(falsy); 5 | assert.equal(truthy, falsy); 6 | -------------------------------------------------------------------------------- /test/fixtures/with-file-sourcemap.js: -------------------------------------------------------------------------------- 1 | var Person, assert; 2 | 3 | assert = require('power-assert'); 4 | 5 | Person = (function() { 6 | function Person(name, age) { 7 | this.name = name; 8 | this.age = age; 9 | } 10 | 11 | return Person; 12 | 13 | })(); 14 | 15 | describe("various types", function() { 16 | beforeEach(function() { 17 | return this.types = [ 18 | "string", 98.6, true, false, null, undefined, ["nested", "array"], { 19 | object: true 20 | }, NaN, Infinity, /^not/, new Person("alice", 3) 21 | ]; 22 | }); 23 | return it("demo", function() { 24 | var bob, index; 25 | index = this.types.length - 1; 26 | bob = new Person("bob", 5); 27 | return assert(this.types[index].name === bob.name); 28 | }); 29 | }); 30 | 31 | //# sourceMappingURL=with-file-sourcemap.js.map 32 | -------------------------------------------------------------------------------- /test/fixtures/with-file-sourcemap.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"with-file-sourcemap.js","sourceRoot":"","sources":["with-file-sourcemap.coffee"],"names":[],"mappings":"AAAA,IAAA,cAAA;;AAAA,MAAA,GAAS,OAAA,CAAQ,cAAR,CAAT,CAAA;;AAAA;AAGe,EAAA,gBAAC,IAAD,EAAO,GAAP,GAAA;AACX,IAAA,IAAC,CAAA,IAAD,GAAQ,IAAR,CAAA;AAAA,IACA,IAAC,CAAA,GAAD,GAAO,GADP,CADW;EAAA,CAAb;;gBAAA;;IAHF,CAAA;;AAAA,QAOA,CAAS,eAAT,EAA0B,SAAA,GAAA;AACxB,EAAA,UAAA,CAAW,SAAA,GAAA;WACT,IAAC,CAAA,KAAD,GAAS;MACP,QADO,EAEP,IAFO,EAGP,IAHO,EAIP,KAJO,EAKP,IALO,EAMP,SANO,EAOP,CACE,QADF,EAEE,OAFF,CAPO,EAWP;AAAA,QACE,MAAA,EAAQ,IADV;OAXO,EAcP,GAdO,EAeP,QAfO,EAgBP,MAhBO,EAiBH,IAAA,MAAA,CAAO,OAAP,EAAgB,CAAhB,CAjBG;MADA;EAAA,CAAX,CAAA,CAAA;SAqBA,EAAA,CAAG,MAAH,EAAW,SAAA,GAAA;AACT,QAAA,UAAA;AAAA,IAAA,KAAA,GAAQ,IAAC,CAAA,KAAK,CAAC,MAAP,GAAgB,CAAxB,CAAA;AAAA,IACA,GAAA,GAAU,IAAA,MAAA,CAAO,KAAP,EAAc,CAAd,CADV,CAAA;WAEA,MAAA,CAAO,IAAC,CAAA,KAAM,CAAA,KAAA,CAAM,CAAC,IAAd,KAAsB,GAAG,CAAC,IAAjC,EAHS;EAAA,CAAX,EAtBwB;AAAA,CAA1B,CAPA,CAAA","sourcesContent":["assert = require 'power-assert'\n\nclass Person\n constructor: (name, age) ->\n @name = name\n @age = age\n\ndescribe \"various types\", ->\n beforeEach ->\n @types = [\n \"string\"\n 98.6\n true\n false\n null\n `undefined`\n [\n \"nested\"\n \"array\"\n ]\n {\n object: true\n }\n NaN\n Infinity\n /^not/\n new Person(\"alice\", 3)\n ]\n\n it \"demo\", ->\n index = @types.length - 1\n bob = new Person(\"bob\", 5)\n assert @types[index].name is bob.name\n"]} 2 | -------------------------------------------------------------------------------- /test/fixtures/with-sourcemap.js: -------------------------------------------------------------------------------- 1 | var Person, assert; 2 | 3 | assert = require('power-assert'); 4 | 5 | Person = (function() { 6 | function Person(name, age) { 7 | this.name = name; 8 | this.age = age; 9 | } 10 | 11 | return Person; 12 | 13 | })(); 14 | 15 | describe("various types", function() { 16 | beforeEach(function() { 17 | return this.types = [ 18 | "string", 98.6, true, false, null, undefined, ["nested", "array"], { 19 | object: true 20 | }, NaN, Infinity, /^not/, new Person("alice", 3) 21 | ]; 22 | }); 23 | return it("demo", function() { 24 | var bob, index; 25 | index = this.types.length - 1; 26 | bob = new Person("bob", 5); 27 | return assert(this.types[index].name === bob.name); 28 | }); 29 | }); 30 | 31 | 32 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL3Rha3V0by93b3JrL2dpdC1zYW5kYm94L2dpdGh1Yi9QT1dFUkFTU0VSVC9lc3Bvd2VyaWZ5LWV4YW1wbGUvdGVzdC9ub2RlL2NvZmZlZV9zY3JpcHRfdGVzdC5jb2ZmZWUiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIvYWJzb2x1dGUvcGF0aC90by9jb2ZmZWVfc2NyaXB0X3Rlc3QuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQUEsY0FBQTs7QUFBQSxNQUFBLEdBQVMsT0FBQSxDQUFRLGNBQVIsQ0FBVCxDQUFBOztBQUFBO0FBR2UsRUFBQSxnQkFBQyxJQUFELEVBQU8sR0FBUCxHQUFBO0FBQ1gsSUFBQSxJQUFDLENBQUEsSUFBRCxHQUFRLElBQVIsQ0FBQTtBQUFBLElBQ0EsSUFBQyxDQUFBLEdBQUQsR0FBTyxHQURQLENBRFc7RUFBQSxDQUFiOztnQkFBQTs7SUFIRixDQUFBOztBQUFBLFFBT0EsQ0FBUyxlQUFULEVBQTBCLFNBQUEsR0FBQTtBQUN4QixFQUFBLFVBQUEsQ0FBVyxTQUFBLEdBQUE7V0FDVCxJQUFDLENBQUEsS0FBRCxHQUFTO01BQ1AsUUFETyxFQUVQLElBRk8sRUFHUCxJQUhPLEVBSVAsS0FKTyxFQUtQLElBTE8sRUFNUCxTQU5PLEVBT1AsQ0FDRSxRQURGLEVBRUUsT0FGRixDQVBPLEVBV1A7QUFBQSxRQUNFLE1BQUEsRUFBUSxJQURWO09BWE8sRUFjUCxHQWRPLEVBZVAsUUFmTyxFQWdCUCxNQWhCTyxFQWlCSCxJQUFBLE1BQUEsQ0FBTyxPQUFQLEVBQWdCLENBQWhCLENBakJHO01BREE7RUFBQSxDQUFYLENBQUEsQ0FBQTtTQXFCQSxFQUFBLENBQUcsTUFBSCxFQUFXLFNBQUEsR0FBQTtBQUNULFFBQUEsVUFBQTtBQUFBLElBQUEsS0FBQSxHQUFRLElBQUMsQ0FBQSxLQUFLLENBQUMsTUFBUCxHQUFnQixDQUF4QixDQUFBO0FBQUEsSUFDQSxHQUFBLEdBQVUsSUFBQSxNQUFBLENBQU8sS0FBUCxFQUFjLENBQWQsQ0FEVixDQUFBO1dBRUEsTUFBQSxDQUFPLElBQUMsQ0FBQSxLQUFNLENBQUEsS0FBQSxDQUFNLENBQUMsSUFBZCxLQUFzQixHQUFHLENBQUMsSUFBakMsRUFIUztFQUFBLENBQVgsRUF0QndCO0FBQUEsQ0FBMUIsQ0FQQSxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiYXNzZXJ0ID0gcmVxdWlyZSAncG93ZXItYXNzZXJ0J1xuXG5jbGFzcyBQZXJzb25cbiAgY29uc3RydWN0b3I6IChuYW1lLCBhZ2UpIC0+XG4gICAgQG5hbWUgPSBuYW1lXG4gICAgQGFnZSA9IGFnZVxuXG5kZXNjcmliZSBcInZhcmlvdXMgdHlwZXNcIiwgLT5cbiAgYmVmb3JlRWFjaCAtPlxuICAgIEB0eXBlcyA9IFtcbiAgICAgIFwic3RyaW5nXCJcbiAgICAgIDk4LjZcbiAgICAgIHRydWVcbiAgICAgIGZhbHNlXG4gICAgICBudWxsXG4gICAgICBgdW5kZWZpbmVkYFxuICAgICAgW1xuICAgICAgICBcIm5lc3RlZFwiXG4gICAgICAgIFwiYXJyYXlcIlxuICAgICAgXVxuICAgICAge1xuICAgICAgICBvYmplY3Q6IHRydWVcbiAgICAgIH1cbiAgICAgIE5hTlxuICAgICAgSW5maW5pdHlcbiAgICAgIC9ebm90L1xuICAgICAgbmV3IFBlcnNvbihcImFsaWNlXCIsIDMpXG4gICAgXVxuXG4gIGl0IFwiZGVtb1wiLCAtPlxuICAgIGluZGV4ID0gQHR5cGVzLmxlbmd0aCAtIDFcbiAgICBib2IgPSBuZXcgUGVyc29uKFwiYm9iXCIsIDUpXG4gICAgYXNzZXJ0IEB0eXBlc1tpbmRleF0ubmFtZSBpcyBib2IubmFtZVxuIl19 33 | -------------------------------------------------------------------------------- /test/paths_test.js: -------------------------------------------------------------------------------- 1 | var espowerSource = require('..'); 2 | var acorn = require('acorn'); 3 | require('acorn-es7-plugin')(acorn); 4 | var escodegen = require('escodegen'); 5 | var sourceMap = require('source-map'); 6 | var convert = require('convert-source-map'); 7 | var extend = require('xtend'); 8 | var assert = require('assert'); 9 | 10 | describe('incoming SourceMap support', function () { 11 | 12 | function withIncomingInlineSourceMap(testName, config) { 13 | it(testName + ' with inline SourceMap: ' + config.inlineSourceMap, function () { 14 | var originalCode = 'var str = "foo";\nvar anotherStr = "bar"\n\nassert.equal(\nstr,\nanotherStr\n);'; 15 | var incomingCodeAndMap = escodegen.generate(acorn.parse(originalCode, {locations: true, sourceFile: config.incomingFilepath, plugins: {asyncawait:true}}), { 16 | format: { 17 | compact: true 18 | }, 19 | sourceMap: config.incomingFilepath, 20 | sourceMapRoot: config.incomingSourceMapRoot, 21 | sourceContent: originalCode, 22 | sourceMapWithCode: true 23 | }); 24 | 25 | var incomingCode = incomingCodeAndMap.code; 26 | // console.log(incomingCode); 27 | var incomingSourceMap = incomingCodeAndMap.map.toString(); 28 | // console.log(incomingSourceMap); 29 | 30 | var espowerOptions = { 31 | patterns: [ 32 | 'assert.equal(actual, expected, [message])' 33 | ], 34 | sourceRoot: config.espowerSourceRoot 35 | }; 36 | 37 | if (config.inlineSourceMap) { 38 | incomingCode = incomingCode + '\n' + convert.fromJSON(incomingSourceMap).toComment() + '\n'; 39 | } else { 40 | espowerOptions.sourceMap = incomingSourceMap; 41 | } 42 | var intermediateFilepath = '/path/to/absolute/intermediate/transformed_test.js'; 43 | var result = espowerSource(incomingCode, intermediateFilepath, espowerOptions); 44 | var compactCode = escodegen.generate(acorn.parse(convert.removeComments(result), {plugins: {asyncawait: true}}), {format: {compact: true}}); 45 | 46 | assert.equal(compactCode, "var _PowerAssertRecorder1=function(){function PowerAssertRecorder(){this.captured=[];}PowerAssertRecorder.prototype._capt=function _capt(value,espath){this.captured.push({value:value,espath:espath});return value;};PowerAssertRecorder.prototype._expr=function _expr(value,source){var capturedValues=this.captured;this.captured=[];return{powerAssertContext:{value:value,events:capturedValues},source:source};};return PowerAssertRecorder;}();var _rec1=new _PowerAssertRecorder1();var _rec2=new _PowerAssertRecorder1();var str='foo';var anotherStr='bar';assert.equal(_rec1._expr(_rec1._capt(str,'arguments/0'),{content:'assert.equal(str, anotherStr)',filepath:'" + config.filepathInGeneratedCode + "',line:4}),_rec2._expr(_rec2._capt(anotherStr,'arguments/1'),{content:'assert.equal(str, anotherStr)',filepath:'" + config.filepathInGeneratedCode + "',line:4}));"); 47 | 48 | var outgoingSourceMap = convert.fromSource(result).toObject(); 49 | assert.equal(outgoingSourceMap.sources.length, 1); 50 | assert.equal(outgoingSourceMap.sources[0], config.filepathInSourceMap, 'filepath of outgoing SourceMap'); 51 | assert.equal(outgoingSourceMap.sourcesContent.length, 1); 52 | assert.equal(outgoingSourceMap.sourcesContent[0], originalCode, 'sourcesContent of outgoing SourceMap'); 53 | assert.equal(outgoingSourceMap.sourceRoot, config.sourceRootInOutgoingSourceMap, 'sourcesRoot of outgoing SourceMap'); 54 | }); 55 | } 56 | 57 | function incomingSourceMapTest (testName, config) { 58 | withIncomingInlineSourceMap(testName, extend(config, {inlineSourceMap: false})); 59 | withIncomingInlineSourceMap(testName, extend(config, {inlineSourceMap: true})); 60 | } 61 | 62 | incomingSourceMapTest('filepath in sourceMap is absolute', { 63 | incomingFilepath: '/path/to/absolute/original_test.js', 64 | incomingSourceMapRoot: undefined, 65 | espowerSourceRoot: undefined, 66 | filepathInGeneratedCode: 'original_test.js', 67 | filepathInSourceMap: '/path/to/absolute/original_test.js', 68 | sourceRootInOutgoingSourceMap: undefined 69 | }); 70 | 71 | incomingSourceMapTest('filepath in sourceMap is relative', { 72 | incomingFilepath: 'relative/original_test.js', 73 | incomingSourceMapRoot: undefined, 74 | espowerSourceRoot: undefined, 75 | filepathInGeneratedCode: 'relative/original_test.js', 76 | filepathInSourceMap: 'relative/original_test.js', 77 | sourceRootInOutgoingSourceMap: undefined 78 | }); 79 | 80 | incomingSourceMapTest('when sourceMap.sourceRoot is given and options.sourceRoot is not given', { 81 | incomingFilepath: 'test/original_test.js', 82 | incomingSourceMapRoot: '/path/to/base', 83 | espowerSourceRoot: undefined, 84 | filepathInGeneratedCode: 'test/original_test.js', 85 | filepathInSourceMap: 'test/original_test.js', 86 | sourceRootInOutgoingSourceMap: '/path/to/base' 87 | }); 88 | 89 | incomingSourceMapTest('when options.sourceRoot is given and sourceMap.sourceRoot is not given', { 90 | incomingFilepath: '/path/to/project/test/original_test.js', 91 | incomingSourceMapRoot: undefined, 92 | espowerSourceRoot: '/path/to/project/', 93 | filepathInGeneratedCode: 'test/original_test.js', 94 | filepathInSourceMap: '/path/to/project/test/original_test.js', 95 | sourceRootInOutgoingSourceMap: undefined 96 | }); 97 | 98 | incomingSourceMapTest('when both options.sourceRoot and sourceMap.sourceRoot are given, options.sourceRoot has precedence over sourceMap.sourceRoot', { 99 | incomingFilepath: 'project/test/original_test.js', 100 | incomingSourceMapRoot: '/path/to', 101 | espowerSourceRoot: '/path/to/project/', 102 | filepathInGeneratedCode: 'test/original_test.js', 103 | filepathInSourceMap: 'project/test/original_test.js', 104 | sourceRootInOutgoingSourceMap: '/path/to' 105 | }); 106 | 107 | incomingSourceMapTest('when path in sourceMap is already relative, just use it even if sourceRoot exists', { 108 | incomingFilepath: 'already/relative/test.js', 109 | incomingSourceMapRoot: undefined, 110 | espowerSourceRoot: '/path/to/project/test/already/relative', 111 | filepathInGeneratedCode: 'already/relative/test.js', 112 | filepathInSourceMap: 'already/relative/test.js', 113 | sourceRootInOutgoingSourceMap: undefined 114 | }); 115 | 116 | incomingSourceMapTest('incoming absolute filepath conflicts with sourceMap.sourceRoot', { 117 | incomingFilepath: '/some/path/to/project/test/original_test.js', 118 | incomingSourceMapRoot: '/another/path/to/project/', 119 | espowerSourceRoot: undefined, 120 | filepathInGeneratedCode: 'original_test.js', 121 | filepathInSourceMap: '/some/path/to/project/test/original_test.js', 122 | sourceRootInOutgoingSourceMap: '/another/path/to/project/' 123 | }); 124 | 125 | incomingSourceMapTest('when filepath is relative and sourceMap.sourceRoot is locating source files on a server, and options.sourceRoot is given, then try to create relative path', { 126 | incomingFilepath: 'test/original_test.js', 127 | incomingSourceMapRoot: 'http://example.com/www/js/', 128 | espowerSourceRoot: '/path/to/project/', 129 | filepathInGeneratedCode: 'test/original_test.js', 130 | filepathInSourceMap: 'test/original_test.js', 131 | sourceRootInOutgoingSourceMap: 'http://example.com/www/js/' 132 | }); 133 | 134 | incomingSourceMapTest('when filepath is absolute and sourceMap.sourceRoot is locating source files on a server, and options.sourceRoot is given, then fallback on basename', { 135 | incomingFilepath: '/path/to/project/test/original_test.js', 136 | incomingSourceMapRoot: 'http://example.com/www/js/', 137 | espowerSourceRoot: '/path/to/project/', 138 | filepathInGeneratedCode: 'original_test.js', 139 | filepathInSourceMap: '/path/to/project/test/original_test.js', 140 | sourceRootInOutgoingSourceMap: 'http://example.com/www/js/' 141 | }); 142 | }); 143 | 144 | 145 | 146 | describe('without incoming SourceMap', function () { 147 | 148 | function withoutIncomingSourceMapTest (testName, config) { 149 | it(testName, function () { 150 | var originalCode = 'var str = "foo";\nvar anotherStr = "bar"\n\nassert.equal(\nstr,\nanotherStr\n);'; 151 | var espowerOptions = { 152 | patterns: [ 153 | 'assert.equal(actual, expected, [message])' 154 | ] 155 | }; 156 | if (config.espowerSourceRoot) { 157 | espowerOptions.sourceRoot = config.espowerSourceRoot; 158 | } 159 | if (config.espowerPath) { 160 | espowerOptions.path = config.espowerPath; 161 | } 162 | 163 | var result = espowerSource(originalCode, config.incomingFilepath, espowerOptions); 164 | var compactCode = escodegen.generate(acorn.parse(convert.removeComments(result), {plugins: {asyncawait: true}}), {format: {compact: true}}); 165 | 166 | assert.equal(compactCode, "var _PowerAssertRecorder1=function(){function PowerAssertRecorder(){this.captured=[];}PowerAssertRecorder.prototype._capt=function _capt(value,espath){this.captured.push({value:value,espath:espath});return value;};PowerAssertRecorder.prototype._expr=function _expr(value,source){var capturedValues=this.captured;this.captured=[];return{powerAssertContext:{value:value,events:capturedValues},source:source};};return PowerAssertRecorder;}();var _rec1=new _PowerAssertRecorder1();var _rec2=new _PowerAssertRecorder1();var str='foo';var anotherStr='bar';assert.equal(_rec1._expr(_rec1._capt(str,'arguments/0'),{content:'assert.equal(str, anotherStr)',filepath:'" + config.filepathInGeneratedCode + "',line:4}),_rec2._expr(_rec2._capt(anotherStr,'arguments/1'),{content:'assert.equal(str, anotherStr)',filepath:'" + config.filepathInGeneratedCode + "',line:4}));"); 167 | 168 | var outgoingSourceMap = convert.fromSource(result).toObject(); 169 | assert.equal(outgoingSourceMap.sources.length, 1); 170 | assert.equal(outgoingSourceMap.sources[0], config.filepathInSourceMap, 'filepathInSourceMap'); 171 | assert.equal(outgoingSourceMap.sourcesContent.length, 1); 172 | assert.equal(outgoingSourceMap.sourcesContent[0], originalCode); 173 | assert.equal(outgoingSourceMap.sourceRoot, config.sourceRootInOutgoingSourceMap); 174 | }); 175 | } 176 | 177 | withoutIncomingSourceMapTest('incoming filepath is absolute', { 178 | incomingFilepath: '/path/to/absolute/original_test.js', 179 | espowerSourceRoot: undefined, 180 | filepathInGeneratedCode: 'original_test.js', 181 | filepathInSourceMap: '/path/to/absolute/original_test.js', 182 | sourceRootInOutgoingSourceMap: undefined 183 | }); 184 | 185 | withoutIncomingSourceMapTest('incoming filepath is relative', { 186 | incomingFilepath: 'relative/original_test.js', 187 | espowerSourceRoot: undefined, 188 | filepathInGeneratedCode: 'relative/original_test.js', 189 | filepathInSourceMap: 'relative/original_test.js', 190 | sourceRootInOutgoingSourceMap: undefined 191 | }); 192 | 193 | withoutIncomingSourceMapTest('incoming filepath is absolute and options.sourceRoot is given', { 194 | incomingFilepath: '/path/to/project/test/original_test.js', 195 | espowerSourceRoot: '/path/to/project/', 196 | filepathInGeneratedCode: 'test/original_test.js', 197 | filepathInSourceMap: 'test/original_test.js', 198 | sourceRootInOutgoingSourceMap: '/path/to/project/' 199 | }); 200 | 201 | withoutIncomingSourceMapTest('incoming filepath is relative and options.sourceRoot is given', { 202 | incomingFilepath: 'test/original_test.js', 203 | espowerSourceRoot: '/path/to/project/', 204 | filepathInGeneratedCode: 'test/original_test.js', 205 | filepathInSourceMap: 'test/original_test.js', 206 | sourceRootInOutgoingSourceMap: '/path/to/project/' 207 | }); 208 | 209 | withoutIncomingSourceMapTest('when incoming relative filepath and options.sourceRoot is overlapped', { 210 | incomingFilepath: 'any/great/project/test/original_test.js', 211 | espowerSourceRoot: '/path/to/any/great/project/', 212 | filepathInGeneratedCode: 'any/great/project/test/original_test.js', 213 | filepathInSourceMap: 'any/great/project/test/original_test.js', 214 | sourceRootInOutgoingSourceMap: '/path/to/any/great/project/' 215 | }); 216 | 217 | withoutIncomingSourceMapTest('when incoming absolute filepath conflicts with options.sourceRoot', { 218 | incomingFilepath: '/root/some/path/to/project/test/original_test.js', 219 | espowerSourceRoot: '/root/another/path/to/project/', 220 | filepathInGeneratedCode: 'original_test.js', 221 | filepathInSourceMap: '../../../../some/path/to/project/test/original_test.js', 222 | sourceRootInOutgoingSourceMap: '/root/another/path/to/project/' 223 | }); 224 | 225 | 226 | 227 | withoutIncomingSourceMapTest('options.path has precedence over filepath argument and affects only on filepath in generated code', { 228 | incomingFilepath: '/absolute/path/to/relative/original_test.js', 229 | espowerSourceRoot: undefined, 230 | espowerPath: 'relative/original_test.js', 231 | filepathInGeneratedCode: 'relative/original_test.js', 232 | filepathInSourceMap: '/absolute/path/to/relative/original_test.js', 233 | sourceRootInOutgoingSourceMap: undefined 234 | }); 235 | 236 | withoutIncomingSourceMapTest('all of filepath, options.path and options.sourceRoot are given', { 237 | incomingFilepath: '/absolute/path/to/relative/original_test.js', 238 | espowerSourceRoot: '/absolute/path/to/', 239 | espowerPath: 'relative/original_test.js', 240 | filepathInGeneratedCode: 'relative/original_test.js', 241 | filepathInSourceMap: 'relative/original_test.js', 242 | sourceRootInOutgoingSourceMap: '/absolute/path/to/' 243 | }); 244 | }); 245 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var espowerSource = require('..'); 2 | var espower = require('espower'); 3 | var sourceMap = require('source-map'); 4 | var convert = require('convert-source-map'); 5 | var fs = require('fs'); 6 | var assert = require('assert'); 7 | 8 | describe('with default options', function() { 9 | beforeEach(function () { 10 | this.path = 'test/fixtures/example.js'; 11 | this.input = fs.readFileSync('test/fixtures/example.js', 'utf8'), 12 | this.output = espowerSource(this.input, this.path); 13 | this.map = convert.fromSource(this.output).toObject(); 14 | }); 15 | 16 | it('should return a string', function() { 17 | assert.equal(typeof this.output, 'string'); 18 | }); 19 | 20 | it('should transform source', function() { 21 | var expected = fs.readFileSync('test/expected/example.js', 'utf8'); 22 | assert.equal(this.output, expected); 23 | }); 24 | 25 | describe('generated sourceMap', function() { 26 | testSourceMapCommonAttributes(); 27 | it('names', function () { 28 | assert.deepEqual(this.map.names, [ 29 | "_PowerAssertRecorder1", "PowerAssertRecorder", "captured", "prototype", 30 | "_capt", "value", "espath", "push", 31 | "_expr", "source", "capturedValues", "powerAssertContext", "events", 32 | "_rec1", "_rec2", "_rec3", 33 | "assert", "require", "truthy", "falsy", "content", "filepath", "line", "equal" 34 | ]); 35 | }); 36 | it('mappings', function () { 37 | assert.equal(this.map.mappings, 'AAAA,IAAAA,qBAAA;AAAA,aAAAC,mBAAA;AAAA,aAAAC,QAAA;AAAA;AAAA,IAAAD,mBAAA,CAAAE,SAAA,CAAAC,KAAA,YAAAA,KAAA,CAAAC,KAAA,EAAAC,MAAA;AAAA,aAAAJ,QAAA,CAAAK,IAAA;AAAA,YAAAF,KAAA,EAAAA,KAAA;AAAA,YAAAC,MAAA,EAAAA,MAAA;AAAA;AAAA,eAAAD,KAAA;AAAA;AAAA,IAAAJ,mBAAA,CAAAE,SAAA,CAAAK,KAAA,YAAAA,KAAA,CAAAH,KAAA,EAAAI,MAAA;AAAA,YAAAC,cAAA,QAAAR,QAAA;AAAA,aAAAA,QAAA;AAAA;AAAA,YAAAS,kBAAA;AAAA,gBAAAN,KAAA,EAAAA,KAAA;AAAA,gBAAAO,MAAA,EAAAF,cAAA;AAAA;AAAA,YAAAD,MAAA,EAAAA,MAAA;AAAA;AAAA;AAAA,WAAAR,mBAAA;AAAA;AAGO,IAAAY,KAAA,OAAAb,qBAAA,GAHP;AAIa,IAAAc,KAAA,OAAAd,qBAAA,GAJb;AAIqB,IAAAe,KAAA,OAAAf,qBAAA,GAJrB;AAAA,IAAIgB,MAAA,GAASC,OAAA,CAAQ,cAAR,CAAb,EACIC,MAAA,GAAS,MADb,EAEIC,KAAA,GAAQ,OAFZ;AAGAH,MAAA,CAAOH,KAAA,CAAAL,KAAA,CAAAK,KAAA,CAAAT,KAAA,CAAAe,KAAA;AAAA,IAAAC,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAAP,EAHA;AAIAN,MAAA,CAAOO,KAAP,CAAaT,KAAA,CAAAN,KAAA,CAAAM,KAAA,CAAAV,KAAA,CAAAc,MAAA;AAAA,IAAAE,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAAb,EAAqBP,KAAA,CAAAP,KAAA,CAAAO,KAAA,CAAAX,KAAA,CAAAe,KAAA;AAAA,IAAAC,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAArB'); 38 | }); 39 | }); 40 | 41 | describe('consuming generated sourceMap', function () { 42 | beforeEach(function () { 43 | this.consumer = new sourceMap.SourceMapConsumer(this.map); 44 | var mappings = []; 45 | this.consumer.eachMapping(function (mapping) { 46 | mappings.push(mapping); 47 | }); 48 | this.mappings = mappings; 49 | }); 50 | it('mapping count', function () { 51 | assert.equal(this.mappings.length, 194); 52 | }); 53 | it('mapping with names', function () { 54 | var withNames = this.mappings.filter(function (mapping) { return mapping.name; }); 55 | assert.equal(withNames.length, 70); 56 | }); 57 | it('originalPosition', function () { 58 | assert.deepEqual(this.consumer.originalPositionFor({line:28,column:4}), 59 | {source:'test/fixtures/example.js',line:1,column:4,name:'assert'}); 60 | assert.deepEqual(this.consumer.originalPositionFor({line:28,column:38}), 61 | {source:'test/fixtures/example.js',line:2,column:4,name:'truthy'}); 62 | assert.deepEqual(this.consumer.originalPositionFor({line:28,column:55}), 63 | {source:'test/fixtures/example.js',line:3,column:4,name:'falsy'}); 64 | assert.deepEqual(this.consumer.originalPositionFor({line:34,column:7}), 65 | {source:'test/fixtures/example.js',line:5,column:7,name:'equal'}); 66 | }); 67 | }); 68 | }); 69 | 70 | 71 | describe('with customized options', function() { 72 | beforeEach(function () { 73 | this.path = 'test/fixtures/customized.js'; 74 | this.input = fs.readFileSync('test/fixtures/customized.js', 'utf8'), 75 | this.output = espowerSource(this.input, this.path, { 76 | patterns: [ 77 | 'refute(actual, [message])', 78 | 'refute.same(actual, expected, [message])', 79 | 'refute.isNull(object, [message])' 80 | ] 81 | }); 82 | this.map = convert.fromSource(this.output).toObject(); 83 | }); 84 | 85 | it('should return a string', function() { 86 | assert.equal(typeof this.output, 'string'); 87 | }); 88 | 89 | it('should transform source', function() { 90 | var expected = fs.readFileSync('test/expected/customized.js', 'utf8'); 91 | assert.equal(this.output, expected); 92 | }); 93 | 94 | describe('generated sourceMap', function() { 95 | testSourceMapCommonAttributes(); 96 | it('names', function () { 97 | assert.deepEqual(this.map.names, [ 98 | "_PowerAssertRecorder1", "PowerAssertRecorder", "captured", "prototype", 99 | "_capt", "value", "espath", "push", 100 | "_expr", "source", "capturedValues", "powerAssertContext", "events", 101 | "_rec1", "_rec2", "_rec3", "_rec4", 102 | "empower","require","formatter","busterAssertions","refute","targetMethods","oneArg","twoArgs","truthy","falsy","content","filepath","line","isNull","same" 103 | ]); 104 | }); 105 | it('mappings', function () { 106 | assert.equal(this.map.mappings, 'AAAA,IAAAA,qBAAA;AAAA,aAAAC,mBAAA;AAAA,aAAAC,QAAA;AAAA;AAAA,IAAAD,mBAAA,CAAAE,SAAA,CAAAC,KAAA,YAAAA,KAAA,CAAAC,KAAA,EAAAC,MAAA;AAAA,aAAAJ,QAAA,CAAAK,IAAA;AAAA,YAAAF,KAAA,EAAAA,KAAA;AAAA,YAAAC,MAAA,EAAAA,MAAA;AAAA;AAAA,eAAAD,KAAA;AAAA;AAAA,IAAAJ,mBAAA,CAAAE,SAAA,CAAAK,KAAA,YAAAA,KAAA,CAAAH,KAAA,EAAAI,MAAA;AAAA,YAAAC,cAAA,QAAAR,QAAA;AAAA,aAAAA,QAAA;AAAA;AAAA,YAAAS,kBAAA;AAAA,gBAAAN,KAAA,EAAAA,KAAA;AAAA,gBAAAO,MAAA,EAAAF,cAAA;AAAA;AAAA,YAAAD,MAAA,EAAAA,MAAA;AAAA;AAAA;AAAA,WAAAR,mBAAA;AAAA;AAMO,IAAAY,KAAA,OAAAb,qBAAA,GANP;AAOc,IAAAc,KAAA,OAAAd,qBAAA,GAPd;AAQY,IAAAe,KAAA,OAAAf,qBAAA,GARZ;AAQoB,IAAAgB,KAAA,OAAAhB,qBAAA,GARpB;AAAA,IAAIiB,OAAA,GAAUC,OAAA,CAAQ,SAAR,CAAd,EACIC,SAAA,GAAYD,OAAA,CAAQ,wBAAR,CADhB,EAEIE,gBAAA,GAAmBF,OAAA,CAAQ,mBAAR,CAFvB,EAGIG,MAAA,GAASJ,OAAA,CAAQG,gBAAA,CAAiBC,MAAzB,EAAiCF,SAAA,EAAjC,EAA8C;AAAA,QAAEG,aAAA,EAAe;AAAA,YAAEC,MAAA,EAAQ,CAAC,QAAD,CAAV;AAAA,YAAsBC,OAAA,EAAS,CAAC,MAAD,CAA/B;AAAA,SAAjB;AAAA,KAA9C,CAHb,EAIIC,MAAA,GAAS,MAJb,EAKIC,KAAA,GAAQ,OALZ;AAMAL,MAAA,CAAOR,KAAA,CAAAL,KAAA,CAAAK,KAAA,CAAAT,KAAA,CAAAqB,MAAA;AAAA,IAAAE,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAAP,EANA;AAOAR,MAAA,CAAOS,MAAP,CAAchB,KAAA,CAAAN,KAAA,CAAAM,KAAA,CAAAV,KAAA,CAAAsB,KAAA;AAAA,IAAAC,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAAd,EAPA;AAQAR,MAAA,CAAOU,IAAP,CAAYhB,KAAA,CAAAP,KAAA,CAAAO,KAAA,CAAAX,KAAA,CAAAqB,MAAA;AAAA,IAAAE,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAAZ,EAAoBb,KAAA,CAAAR,KAAA,CAAAQ,KAAA,CAAAZ,KAAA,CAAAsB,KAAA;AAAA,IAAAC,OAAA;AAAA,IAAAC,QAAA;AAAA,IAAAC,IAAA;AAAA,EAApB'); 107 | }); 108 | }); 109 | 110 | describe('consuming generated sourceMap', function () { 111 | beforeEach(function () { 112 | this.consumer = new sourceMap.SourceMapConsumer(this.map); 113 | var mappings = []; 114 | this.consumer.eachMapping(function (mapping) { 115 | mappings.push(mapping); 116 | }); 117 | this.mappings = mappings; 118 | }); 119 | it('mapping count', function () { 120 | assert.equal(this.mappings.length, 275); 121 | }); 122 | it('mapping with names', function () { 123 | var withNames = this.mappings.filter(function (mapping) { return mapping.name; }); 124 | assert.equal(withNames.length, 94); 125 | }); 126 | it('originalPosition', function () { 127 | assert.deepEqual(this.consumer.originalPositionFor({line:29,column:34}), 128 | {source:'test/fixtures/customized.js',line:2,column:4,name:'formatter'}); 129 | assert.deepEqual(this.consumer.originalPositionFor({line:29,column:81}), 130 | {source:'test/fixtures/customized.js',line:3,column:4,name:'busterAssertions'}); 131 | assert.deepEqual(this.consumer.originalPositionFor({line:29,column:130}), 132 | {source:'test/fixtures/customized.js',line:4,column:4,name:'refute'}); 133 | assert.deepEqual(this.consumer.originalPositionFor({line:34,column:8}), 134 | {source:'test/fixtures/customized.js',line:5,column:4,name:'truthy'}); 135 | assert.deepEqual(this.consumer.originalPositionFor({line:34,column:25}), 136 | {source:'test/fixtures/customized.js',line:6,column:4,name:'falsy'}); 137 | assert.deepEqual(this.consumer.originalPositionFor({line:40,column:7}), 138 | {source:'test/fixtures/customized.js',line:8,column:7,name:'isNull'}); 139 | assert.deepEqual(this.consumer.originalPositionFor({line:45,column:7}), 140 | {source:'test/fixtures/customized.js',line:9,column:7,name:'same'}); 141 | }); 142 | }); 143 | }); 144 | 145 | 146 | function testSourceMapCommonAttributes() { 147 | it('version', function () { 148 | assert.equal(this.map.version, 3); 149 | }); 150 | it('sources', function () { 151 | assert.deepEqual(this.map.sources, [this.path]); 152 | }); 153 | it('sourceRoot', function () { 154 | assert(this.map.sourceRoot === undefined); 155 | }); 156 | it('sourcesContent', function () { 157 | assert.deepEqual(this.map.sourcesContent, [this.input]); 158 | }); 159 | it('file', function () { 160 | assert(this.map.file === undefined); 161 | }); 162 | } 163 | 164 | 165 | describe('incoming code with SourceMap comment', function() { 166 | beforeEach(function () { 167 | this.path = 'test/fixtures/with-sourcemap.js'; 168 | this.input = fs.readFileSync('test/fixtures/with-sourcemap.js', 'utf8'), 169 | this.output = espowerSource(this.input, this.path); 170 | this.map = convert.fromSource(this.output).toObject(); 171 | }); 172 | 173 | it('should return a string', function() { 174 | assert.equal(typeof this.output, 'string'); 175 | }); 176 | 177 | it('should transform source', function() { 178 | var expected = fs.readFileSync('test/expected/with-sourcemap.js', 'utf8'); 179 | assert.equal(this.output, expected); 180 | }); 181 | 182 | describe('generated sourceMap', function() { 183 | it('version', function () { 184 | assert.equal(this.map.version, 3); 185 | }); 186 | it('sources', function () { 187 | assert.deepEqual(this.map.sources, ['/absolute/path/to/coffee_script_test.coffee']); 188 | }); 189 | it('sourceRoot', function () { 190 | assert(this.map.sourceRoot === undefined); 191 | }); 192 | it('sourcesContent', function () { 193 | assert.deepEqual(this.map.sourcesContent, [ 194 | [ 195 | 'assert = require \'power-assert\'', 196 | '', 197 | 'class Person', 198 | ' constructor: (name, age) ->', 199 | ' @name = name', 200 | ' @age = age', 201 | '', 202 | 'describe "various types", ->', 203 | ' beforeEach ->', 204 | ' @types = [', 205 | ' "string"', 206 | ' 98.6', 207 | ' true', 208 | ' false', 209 | ' null', 210 | ' `undefined`', 211 | ' [', 212 | ' "nested"', 213 | ' "array"', 214 | ' ]', 215 | ' {', 216 | ' object: true', 217 | ' }', 218 | ' NaN', 219 | ' Infinity', 220 | ' /^not/', 221 | ' new Person("alice", 3)', 222 | ' ]', 223 | '', 224 | ' it "demo", ->', 225 | ' index = @types.length - 1', 226 | ' bob = new Person("bob", 5)', 227 | ' assert @types[index].name is bob.name', 228 | '' 229 | ].join('\n') 230 | ]); 231 | }); 232 | it('file', function () { 233 | assert(this.map.file === undefined); 234 | }); 235 | it('names', function () { 236 | assert.deepEqual(this.map.names, []); 237 | }); 238 | it('mappings', function () { 239 | assert.equal(this.map.mappings, 'AAAA,IAAA,qBAAA;AAAA,aAAA,mBAAA;AAAA,aAAA,QAAA;AAAA;AAAA,IAAA,mBAAA,CAAA,SAAA,CAAA,KAAA,YAAA,KAAA,CAAA,KAAA,EAAA,MAAA;AAAA,aAAA,QAAA,CAAA,IAAA;AAAA,YAAA,KAAA,EAAA,KAAA;AAAA,YAAA,MAAA,EAAA,MAAA;AAAA;AAAA,eAAA,KAAA;AAAA;AAAA,IAAA,mBAAA,CAAA,SAAA,CAAA,KAAA,YAAA,KAAA,CAAA,KAAA,EAAA,MAAA;AAAA,YAAA,cAAA,QAAA,QAAA;AAAA,aAAA,QAAA;AAAA;AAAA,YAAA,kBAAA;AAAA,gBAAA,KAAA,EAAA,KAAA;AAAA,gBAAA,MAAA,EAAA,cAAA;AAAA;AAAA,YAAA,MAAA,EAAA,MAAA;AAAA;AAAA;AAAA,WAAA,mBAAA;AAAA;AAAA,IAAA,MAAA,EAAA,MAAA;AAAA,MAAA,GAAS,OAAA,CAAQ,cAAR,CAAT,CAAA;AAAA,MAAA,GAAA,YAAA;AAAA,IAGe,SAAA,MAAA,CAAC,IAAD,EAAO,GAAP,EAAA;AAAA,QACX,KAAC,IAAD,GAAQ,IAAR,CADW;AAAA,QAEX,KAAC,GAAD,GAAO,GAAP,CAFW;AAAA,KAHf;AAAA,kBAAA;AAAA,CAAA,EAAA,CAAA;AAAA,QAAA,CAOS,eAPT,EAO0B,YAAA;AAAA,IACxB,UAAA,CAAW,YAAA;AAAA,eACT,KAAC,KAAD,GAAS;AAAA,YACP,QADO;AAAA,YAEP,IAFO;AAAA,YAGP,IAHO;AAAA,YAIP,KAJO;AAAA,YAKP,IALO;AAAA,YAMP,SANO;AAAA,YAOP;AAAA,gBACE,QADF;AAAA,gBAEE,OAFF;AAAA,aAPO;AAAA,YAWP,EACE,MAAA,EAAQ,IADV,EAXO;AAAA,YAcP,GAdO;AAAA,YAeP,QAfO;AAAA,YAgBP,MAhBO;AAAA,YAiBH,IAAA,MAAA,CAAO,OAAP,EAAgB,CAAhB,CAjBG;AAAA,UADA;AAAA,KAAX,EADwB;AAAA,WAsBxB,EAAA,CAAG,MAAH,EAAW,YAAA;AAAA,QAGF,IAAA,KAAA,OAAA,qBAAA,GAHE;AAAA,QACT,IAAA,GAAA,EAAA,KAAA,CADS;AAAA,QACT,KAAA,GAAQ,KAAC,KAAD,CAAO,MAAP,GAAgB,CAAxB,CADS;AAAA,QAET,GAAA,GAAU,IAAA,MAAA,CAAO,KAAP,EAAc,CAAd,CAAV,CAFS;AAAA,eAGT,MAAA,CAAO,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,CAAA,KAAA,MAAC,KAAD,oCAAA,KAAO,CAAA,KAAA,CAAA,KAAA,qCAAP,8BAAc,IAAd,0BAAA,KAAsB,CAAA,KAAA,CAAtB,KAAsB,CAAA,KAAA,CAAA,GAAA,8BAAI,IAAJ,sBAAtB;AAAA,YAAA,OAAA;AAAA,YAAA,QAAA;AAAA,YAAA,IAAA;AAAA,UAAP,EAHS;AAAA,KAAX,EAtBwB;AAAA,CAP1B'); 240 | }); 241 | }); 242 | 243 | describe('consuming generated sourceMap', function () { 244 | beforeEach(function () { 245 | this.consumer = new sourceMap.SourceMapConsumer(this.map); 246 | var mappings = []; 247 | this.consumer.eachMapping(function (mapping) { 248 | mappings.push(mapping); 249 | }); 250 | this.mappings = mappings; 251 | }); 252 | it('mapping count', function () { 253 | assert.equal(this.mappings.length, 320); 254 | }); 255 | it('mapping with names', function () { 256 | var withNames = this.mappings.filter(function (mapping) { return mapping.name; }); 257 | assert.equal(withNames.length, 0); 258 | }); 259 | it('originalPosition', function () { 260 | // name 261 | assert.deepEqual(this.consumer.generatedPositionFor({ 262 | source:'/absolute/path/to/coffee_script_test.coffee', 263 | line:4, 264 | column:16 265 | }), { 266 | line:28, 267 | column:20, 268 | lastColumn: null 269 | }); 270 | 271 | assert.deepEqual(this.consumer.originalPositionFor({line:28,column:4}), 272 | {source:'/absolute/path/to/coffee_script_test.coffee',line:4,column:15,name:null}); 273 | 274 | assert.deepEqual(this.consumer.originalPositionFor({line:56,column:8}), 275 | {source:'/absolute/path/to/coffee_script_test.coffee',line:31,column:4,name:null}); 276 | 277 | assert.deepEqual(this.consumer.originalPositionFor({line:59,column:15}), 278 | {source:'/absolute/path/to/coffee_script_test.coffee',line:33,column:4,name:null}); 279 | }); 280 | }); 281 | }); 282 | 283 | describe('incoming code with file SourceMap comment', function() { 284 | beforeEach(function () { 285 | this.path = 'test/fixtures/with-file-sourcemap.js'; 286 | this.input = fs.readFileSync('test/fixtures/with-file-sourcemap.js', 'utf8'), 287 | this.output = espowerSource(this.input, this.path); 288 | this.map = convert.fromSource(this.output).toObject(); 289 | }); 290 | 291 | it('should transform source', function() { 292 | var expected = fs.readFileSync('test/expected/with-file-sourcemap.js', 'utf8'); 293 | assert.equal(this.output, expected); 294 | }); 295 | 296 | it('sourcesContent', function () { 297 | assert.deepEqual(this.map.sourcesContent, [ 298 | [ 299 | 'assert = require \'power-assert\'', 300 | '', 301 | 'class Person', 302 | ' constructor: (name, age) ->', 303 | ' @name = name', 304 | ' @age = age', 305 | '', 306 | 'describe "various types", ->', 307 | ' beforeEach ->', 308 | ' @types = [', 309 | ' "string"', 310 | ' 98.6', 311 | ' true', 312 | ' false', 313 | ' null', 314 | ' `undefined`', 315 | ' [', 316 | ' "nested"', 317 | ' "array"', 318 | ' ]', 319 | ' {', 320 | ' object: true', 321 | ' }', 322 | ' NaN', 323 | ' Infinity', 324 | ' /^not/', 325 | ' new Person("alice", 3)', 326 | ' ]', 327 | '', 328 | ' it "demo", ->', 329 | ' index = @types.length - 1', 330 | ' bob = new Person("bob", 5)', 331 | ' assert @types[index].name is bob.name', 332 | '' 333 | ].join('\n') 334 | ]); 335 | }); 336 | 337 | describe('consuming generated sourceMap', function () { 338 | beforeEach(function () { 339 | this.consumer = new sourceMap.SourceMapConsumer(this.map); 340 | var mappings = []; 341 | this.consumer.eachMapping(function (mapping) { 342 | mappings.push(mapping); 343 | }); 344 | this.mappings = mappings; 345 | }); 346 | it('mapping count', function () { 347 | assert.equal(this.mappings.length, 320); 348 | }); 349 | it('mapping with names', function () { 350 | var withNames = this.mappings.filter(function (mapping) { return mapping.name; }); 351 | assert.equal(withNames.length, 0); 352 | }); 353 | it('originalPosition', function () { 354 | // name 355 | assert.deepEqual(this.consumer.generatedPositionFor({ 356 | source:'with-file-sourcemap.coffee', 357 | line:4, 358 | column:16 359 | }), { 360 | line:28, 361 | column:20, 362 | lastColumn: null 363 | }); 364 | 365 | assert.deepEqual(this.consumer.originalPositionFor({line:28,column:4}), 366 | {source:'with-file-sourcemap.coffee',line:4,column:15,name:null}); 367 | 368 | assert.deepEqual(this.consumer.originalPositionFor({line:56,column:8}), 369 | {source:'with-file-sourcemap.coffee',line:31,column:4,name:null}); 370 | 371 | assert.deepEqual(this.consumer.originalPositionFor({line:59,column:15}), 372 | {source:'with-file-sourcemap.coffee',line:33,column:4,name:null}); 373 | }); 374 | }); 375 | }); 376 | 377 | 378 | describe('parameter prerequisites', function () { 379 | var code = 'var str = "foo";\nvar anotherStr = "bar"\n\nassert.equal(\nstr,\nanotherStr\n);'; 380 | var filepath = 'relative/original_test.js'; 381 | var options = { 382 | patterns: [ 383 | 'assert.equal(actual, expected, [message])' 384 | ] 385 | }; 386 | 387 | it('`originalCode` is mandatory and throw EspowerError when not specified', function () { 388 | assert.throws(function () { 389 | espowerSource(null, filepath, options); 390 | }, espower.EspowerError); 391 | }); 392 | 393 | it('`filepath` is optional', function () { 394 | assert.doesNotThrow(function () { 395 | espowerSource(code, null, options); 396 | }); 397 | }); 398 | 399 | it('`options` is optional', function () { 400 | assert.doesNotThrow(function () { 401 | espowerSource(code, filepath, null); 402 | }); 403 | }); 404 | 405 | it('does not throw EspowerError when both filepath and options.path are not specified', function () { 406 | assert.doesNotThrow(function () { 407 | espowerSource(code, null, options); 408 | }); 409 | }); 410 | }); 411 | 412 | 413 | describe('when filepath is not specified', function () { 414 | describe('neither filepath nor options.path are not specified', function () { 415 | beforeEach(function () { 416 | var input = fs.readFileSync('test/fixtures/example.js', 'utf8'); 417 | this.output = espowerSource(input); 418 | }); 419 | it('no filepath and sourcemap in output', function () { 420 | var expected = fs.readFileSync('test/expected/example_without_filepath_and_sourcemap.js', 'utf8'); 421 | assert.equal(this.output + '\n', expected); 422 | }); 423 | it('sourcemap will not be attached', function () { 424 | var map = convert.fromSource(this.output); 425 | assert(!map); 426 | }); 427 | }); 428 | 429 | describe('but options.path is given', function () { 430 | beforeEach(function () { 431 | var optionsPath = 'test/fixtures/example.js'; 432 | var input = fs.readFileSync('test/fixtures/example.js', 'utf8'); 433 | this.output = espowerSource(input, null, { path: optionsPath }); 434 | }); 435 | it('filepath in output', function () { 436 | var expected = fs.readFileSync('test/expected/example.js', 'utf8'); 437 | assert.equal(this.output, expected); 438 | }); 439 | it('sourcemap will be attached', function () { 440 | var map = convert.fromSource(this.output); 441 | assert(map); 442 | }); 443 | }); 444 | 445 | describe('and options.path is not specified but inlined sourcemap is given', function () { 446 | beforeEach(function () { 447 | var input = fs.readFileSync('test/fixtures/with-sourcemap.js', 'utf8'); 448 | this.output = espowerSource(input); 449 | }); 450 | it('filepath in output', function () { 451 | var expectedWithSourceMap = fs.readFileSync('test/expected/with-sourcemap.js', 'utf8'); 452 | var expected = convert.removeComments(expectedWithSourceMap); 453 | assert.equal(this.output + '\n\n', expected); 454 | }); 455 | it('sourcemap will not be attached', function () { 456 | var map = convert.fromSource(this.output); 457 | assert(!map); 458 | }); 459 | }); 460 | 461 | describe('and options.path is not specified but options.sourceMap is given', function () { 462 | beforeEach(function () { 463 | var input = fs.readFileSync('test/fixtures/with-sourcemap.js', 'utf8'); 464 | var sourceMapComment = convert.fromSource(input); 465 | var bareCode = convert.removeComments(input); 466 | this.output = espowerSource(bareCode, null, { sourceMap: sourceMapComment.toObject() }); 467 | }); 468 | it('filepath in output', function () { 469 | var expectedWithSourceMap = fs.readFileSync('test/expected/with-sourcemap.js', 'utf8'); 470 | var expected = convert.removeComments(expectedWithSourceMap); 471 | assert.equal(this.output + '\n\n', expected); 472 | }); 473 | it('sourcemap will not be attached', function () { 474 | var map = convert.fromSource(this.output); 475 | assert(!map); 476 | }); 477 | }); 478 | }); 479 | 480 | 481 | describe('empty and blank files', function() { 482 | it('when file content is empty', function() { 483 | var output = espowerSource('', 'path/to/test.js'); 484 | assert.equal(typeof output, 'string'); 485 | assert.equal(output, '\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9\n'); 486 | }); 487 | it('when file content is blank', function() { 488 | var output = espowerSource(' \n \n', 'path/to/test.js'); 489 | assert.equal(typeof output, 'string'); 490 | assert.equal(output, '\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbXX0=\n'); 491 | }); 492 | }); 493 | 494 | describe('syntax error handling', function() { 495 | var source = [ 496 | "var a = 1;", 497 | "var b = 2;", 498 | "var c = 3;", 499 | "", // test empty line 500 | "var e = 5;", 501 | "var f = 6;", 502 | "syntax error at line 7", 503 | "var g = 8;", 504 | "var h = 9;", 505 | "var i = 10;", 506 | "var j = 11;", 507 | "var k = 12;", 508 | "var l = 13;"].join('\n'); 509 | 510 | it('can generate SyntaxError with custom message with 10 lines surrounding the line', function() { 511 | var error; 512 | try { 513 | espowerSource(source, "dummy.js"); 514 | } catch(e) { 515 | error = e; 516 | } 517 | assert(error instanceof SyntaxError); 518 | assert.notEqual(error.message.indexOf(' 2: var b = 2;'), -1); 519 | assert.notEqual(error.message.indexOf(' 4: '), -1); 520 | assert.notEqual(error.message.indexOf(' 7: syntax error at line 7'), -1); 521 | assert.notEqual(error.message.indexOf(' ^'), -1); 522 | assert.notEqual(error.message.indexOf(' 12: var k = 12;'), -1); 523 | }); 524 | }); 525 | 526 | 527 | describe('ES2018 syntax', function() { 528 | beforeEach(function () { 529 | this.path = 'test/fixtures/es2018.js'; 530 | this.input = fs.readFileSync('test/fixtures/es2018.js', 'utf8'), 531 | this.output = espowerSource(this.input, this.path); 532 | this.map = convert.fromSource(this.output).toObject(); 533 | }); 534 | it('should return a string', function() { 535 | assert.equal(typeof this.output, 'string'); 536 | }); 537 | it('should transform source', function() { 538 | var expected = fs.readFileSync('test/expected/es2018.js', 'utf8'); 539 | assert.equal(this.output, expected); 540 | }); 541 | }); 542 | --------------------------------------------------------------------------------