Closed studds closed 8 years ago
For JavaScript projects + babel
it just works by adding the babel-preset-power-assert
preset to the .babelrc
file (or directly passing to the compiler's options).
For TypeScript projects, the easiest way to use power-assert
is to add a babel preprocessor to perform the transformation after TypeScript compilation (so that the compiler will compile .ts
to .js
and then preprocessor will add power-assert stuff to .js
test files).
I have put together a sample project with your config and everything else that you may use as an example.
Note how power-assert produces a verbose error message that is helpful when displayed in the Wallaby (or any other) multiline console, but the same error message displayed inline may not be that helpful for obvious reasons.
So I have also included a small hack to make power-assert to report the original error message as well. It's optional, only required to make inline messages look better.
Wow, @ArtemGovorov, thank you for the fast response - that's great.
Depending on a different compiler chain during dev vs build / prod seems like a suboptimal outcome. Do you think there's any chance that this will be support with typescript directly, rather than via babel?
@studds Sure, wallaby preprocessor can do anything as long as it returns an object with the transformed code and (optionally, but required for the correct stack mapping) the source map.
I have updated the sample to use espower-source
in the preprocessor instead of babel
. I have also taken the source map extraction function from your project.
@ArtemGovorov wow, amazing! Thanks so much!
Hi, I'm still having issues with this. I had to configure my app via Babel as I am using react. The power asset seems to work, yet I'm still getting undefined in some message parts. Also, I am getting really weird inline message.
And a message, please note the unknown:
This is my config (rather large)
module.exports = function(wallaby) {
// var load = require;
return {
files: [
"src/lib/models/*.ts*",
"src/lib/helpers/*.ts*",
"src/client/configs/*.ts*",
"src/client/utils/*.ts*",
"src/client/modules/**/components/*.ts*",
"src/client/modules/**/actions/*.ts",
"src/client/modules/**/containers/*.ts",
"src/client/modules/**/libs/*.ts",
"src/client/modules/**/models/*.ts",
//"src/client/modules/**/stories/*.ts*",
"src/typings/**/*.d.ts",
{ pattern: 'src/**/_stories/*.ts*', ignore: true }
],
tests: [
"src/client/**/stories/*.ts*"
],
compilers: {
"**/*.ts*": wallaby.compilers.typeScript({module: "es6", target: "es6", jsx: "preserve"})
},
preprocessors: {
"**/*.js*": file => require("babel-core").transform(file.content.replace('(\'assert\')', '(\'power-assert\')'), {
sourceMap: true,
presets: ["es2015", "stage-2", "react", "babel-preset-power-assert"],
plugins: ["jsx-control-statements"]
})
},
env: {
type: "node"
},
testFramework: "mocha",
setup: function() {
// setup power asssert
var Module = require('module').Module;
if (!Module._originalRequire) {
const modulePrototype = Module.prototype;
Module._originalRequire = modulePrototype.require;
modulePrototype.require = function (filePath) {
if (filePath === 'empower-core') {
var originalEmpowerCore = Module._originalRequire.call(this, filePath);
var newEmpowerCore = function () {
var originalOnError = arguments[1].onError;
arguments[1].onError = function (errorEvent) {
errorEvent.originalMessage = errorEvent.error.message + '\n';
return originalOnError.apply(this, arguments);
};
return originalEmpowerCore.apply(this, arguments);
};
newEmpowerCore.defaultOptions = originalEmpowerCore.defaultOptions;
return newEmpowerCore;
}
return Module._originalRequire.call(this, filePath);
};
}
// facade for stories
var mocha = require('mocha');
var chai = require('chai');
var chaiEnzyme = require('chai-enzyme');
chai.use(chaiEnzyme());
var storiesOf = function storiesOf() {
console.log('executing ...')
var api = {};
api.addDecorator = () => {
return api;
};
api.add = (name, func)=> {
func();
return api;
};
api.addWithInfo = (name, description, func)=> {
func();
return api;
};
return api;
};
var action = () => {};
var linkTo = () => {};
var specs = (spec) => {
spec();
};
// handle jquery
var jquery = require('jquery');
global.$ = jquery;
global.jQuery = jquery;
global.storiesOf = storiesOf;
global.action = action;
global.linkTo = linkTo;
global.specs = specs;
global.describe = mocha.describe;
global.it = mocha.it;
global.React = require("react");
// Taken from https://github.com/airbnb/enzyme/blob/master/docs/guides/jsdom.md
var jsdom = require('jsdom').jsdom;
var exposedProperties = ['window', 'navigator', 'document'];
global.document = jsdom('');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
}
});
global.navigator = {
userAgent: 'node.js'
};
}
};
};
I'm not sure if I have all the dependencies, this is package.json
{
"name": "nwb-react-tutorial",
"version": "1.0.0",
"description": "An implementation of the React tutorial using nwb middleware",
"private": true,
"scripts": {
"forever": "./node_modules/.bin/forever -a -l /app/logs/f.log -f start --pidFile /app/logs/pids.log server.js",
"compile": "tsc -p app/server",
"build": "nwb build-react-app",
"clean": "nwb clean-app",
"start": "./node_modules/.bin/forever -a -l /app/logs/f.log -f --pidFile /app/logs/pids.log server.js",
"dev": "EXPRESS_PORT=3000 nodemon --watch src/server server.js",
"startClient": "nwb serve-react-app --reload",
"test": "nwb test",
"test:coverage": "nwb test --coverage",
"test:watch": "nwb test --server",
"storybook": "start-storybook -p 9001 -s ./public"
},
"dependencies": {
"apollo-module-date": "^1.0.1",
"apollo-modules": ">0.0.1",
"apollo-server": "^0.2.4",
"bcrypt-nodejs": "0.0.3",
"body-parser": "^1.15.2",
"connect-history-api-fallback": "^1.3.0",
"cors": "^2.8.0",
"dataloader": "^1.2.0",
"express": "^4.14.0",
"forever": "^0.15.2",
"graphql": "^0.6.2",
"graphql-tools": "^0.6.4",
"json-loader": "^0.5.4",
"jsonwebtoken": "^7.1.9",
"meteor-random": "0.0.3",
"meteor-sha256": "^1.0.0",
"mongodb": "^2.2.5",
"morgan": "^1.7.0",
"nodemailer": "^2.5.0",
"remove": "^0.1.5",
"typescript": "rc"
},
"devDependencies": {
"@kadira/react-storybook-addon-info": "^3.2.1",
"@kadira/storybook": "^2.11.0",
"apollo-authentication-semantic-ui": ">=0.0.2",
"apollo-client": "^0.4.11",
"apollo-mantra": "^1.1.0",
"babel-preset-power-assert": "^1.0.0",
"babel-preset-stage-2": "^6.13.0",
"bcrypt-nodejs": "0.0.3",
"chai": "^3.5.0",
"chai-enzyme": "^0.5.1",
"date-format-lite": "^0.9.1",
"enzyme": "^2.4.1",
"graphql-tag": "^0.1.11",
"i18n-client": "0.0.6",
"jquery": "^3.1.0",
"jss": "^5.4.0",
"jss-nested": "^2.1.0",
"jss-vendor-prefixer": "^3.0.0",
"jsx-control-statements": "^3.1.2",
"local-storage": "^1.4.2",
"marked": "^0.3.6",
"meteor-random": "0.0.3",
"mocha": "^3.0.2",
"moment": "^2.14.1",
"morgan": "^1.7.0",
"nwb": "0.12.x",
"power-assert": "^1.4.1",
"raw-loader": "^0.5.1",
"react": "^15.3.1",
"react-addons-test-utils": "^15.3.1",
"react-addons-update": "^15.3.0",
"react-apollo": "^0.4.7",
"react-dom": "^15.3.0",
"react-functional": "^2.0.0",
"react-helmet": "^3.1.0",
"react-hot-loader": "^3.0.0-beta.2",
"react-redux": "^4.4.5",
"react-router": "^2.6.1",
"react-router-redux": "^4.0.5",
"react-s-alert": "^1.1.4",
"redux-form": "^6.0.1",
"redux-form-semantic-ui": "../../packages/redux-form-semantic-ui",
"redux-thunk": "^2.1.0",
"semantic-ui-css": "^2.2.4",
"semanticui-react": "^0.1.53",
"storybook-addon-specifications": "^1.0.15",
"style-loader": "^0.13.1",
"sweetalert2": "^4.1.9"
},
"author": "Tomi Trescak <tomi.trescak@gmail.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": ""
}
}
@tomitrescak Could you please share a small sample project where I could reproduce the issue?
I have disected your setup function and the problem is that the onError function never gets executed :/
// setup power asssert
var Module = require('module').Module;
if (!Module._originalRequire) {
const modulePrototype = Module.prototype;
Module._originalRequire = modulePrototype.require;
modulePrototype.require = function (filePath) {
if (filePath === 'empower-core') {
console.log('GET EXECUTED!');
var originalEmpowerCore = Module._originalRequire.call(this, filePath);
var newEmpowerCore = function () {
var originalOnError = arguments[1].onError;
arguments[1].onError = function (errorEvent) {
console.log('NEVER GETS EXECUTED!: ' + errorEvent.error.message);
errorEvent.originalMessage = errorEvent.error.message + '\n';
return originalOnError.apply(this, arguments);
};
console.log('GET EXECUTED');
return originalEmpowerCore.apply(this, arguments);
};
newEmpowerCore.defaultOptions = originalEmpowerCore.defaultOptions;
return newEmpowerCore;
}
return Module._originalRequire.call(this, filePath);
};
}
It actually does get executed and I see correct message in my console, only inline is showing this long message. But maybe it's by design ?
It actually does get executed and I see correct message in my console, only inline is showing this long message.
Wallaby has always been showing whatever error message an assertion library would provide. So it is expected. However, with the setup function I tried to hack power-assert a bit to just display a better inline message starting with some meaningful info (because it's obviously not possible to display the full nice multiline message inline). I can't yet reproduce it, will have a look into why it doesn't work (as it was hack, perhaps it was broken by their internal changes).
Don't worry about it. I understand now what you tried to do and it works as expected. Thanks!
@tomitrescak Oh, cool. So did you manage to make the shorter/nicer inline messages work?
Sorry, they are not actually shorter, but are starting with the meaningful part :)
@ArtemGovorov Is there a way to get wallaby + typescript + ava + power-assert working?
The wallaby blog post only mentions the required setup when using babel. I tried out different variations including your example above when using ava (instead of mocha) but I can't see any power assert messages.
@geekflyer When ava
module is installed, it also installs all required babel modules as its dependencies, so you may just use it like described in the blog post:
module.exports = function (wallaby) {
return {
...
testFramework: 'ava',
compilers: {
'**/*.js': wallaby.compilers.babel({
plugins: [
require('babel-plugin-espower/create')(
require('babel-core'), {
embedAst: true,
patterns:require('ava/lib/enhance-assert').PATTERNS
})
]
})
}
};
};
Note that I have added the embedAst: true
(in the blog post as well). It's a new option required for power-assert
to work correctly with ava
.
I have also published the new version of wallaby.js core 1.0.302 that embeds the setup
function for better inline messages for ava
runner. So all you need is the config above.
Issue description or question
Power-assert provides descriptive assertion messages through standard assert interface. To do this, power-assert transform test code to look for calls to
assert
and enhance them. I'm wondering how to get this working with wallaby.js?It's pretty simple to add power-assert to the compiler pipeline including sourcemap (an example taking the result from ts-node and passing it through power-assert: https://github.com/tracecomms/espower-ts-node). I'm not sure how
ranges
would need to be created in a custom compiler.Is power-assert support something that could be added to wallaby.js?
Wallaby.js configuration file
Code editor or IDE name and version
WebStorm v11 Atom v1.x
OS name and version
OSX