-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
this.timeout() fails when using ES6's arrow functions #2018
Comments
It binds the function to the test context, which can't be done when using arrow functions. From http://mochajs.org/ Sorry about that! |
Thanks. Why so many "magic" that, at the end, produces problems? Why not this?: var mocha = require('mocha');
mocha.describe('foo', (suite) => {
suite.timeout(100);
suite.it('must love bar', () => ... );
}); No globals, no problematic magic... but just JavaScript. |
What you're proposing is a major breaking change and something that's being discussed in #1969 (comment) A rewrite might introduce those types of semantics :) |
Nice to know. Thanks. |
@ibc well, it would have to be var mocha = require('mocha');
mocha.describe('foo', (suite) => {
suite.timeout(100);
suite.it('must love bar', (suite) => ... );
}); but are the two different suite arguments the same type? probably not, so then you have different variable names to reflect the different types like so var mocha = require('mocha');
mocha.describe('foo', (suite) => {
suite.timeout(100);
suite.it('must love bar', (test) => ... );
}); |
anyway, the arrow operator cannot be used in functions that expect contexts. I don't envision breaking the BDD UI for #1969--right off the bat, anyway--though I could be persuaded. It was my hope that we keep the existing API, and introduce a separate package containing the BDD UI. Mocha will ship with a version of the BDD UI which uses the existing API, but then we can release a new version of the BDD UI package using lambdas thereafter--users can choose whether or not to explicitly upgrade to that package. |
Maybe alternative ES6 syntax for describe({ feature: 'create stuff' , do () {
it('abc', () => {
});
}}) This would at least allow binding at the suite level. |
Any update on this? I have this mocha = require('mocha');
mocha.describe('test', (suite) => {
suite.timeout(500);
suite.it('test', (done)=>
)
}
) And getting TypeError: Cannot read property 'timeout' of undefined |
@mroien this is not a Mocha bug. the arrow syntax is not a 1:1 replacement for |
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Needed to change function from arrow function as they are not supported for mocha tests which require the use of timeout() See: mochajs/mocha#2018
Did anything come of this? I like the proposed solution, if only for my love of arrow functions and aversion to 'this' when it's not required |
Since timeout is only relevant with it('makes sense', done => {
done.timeout(100);
}); |
@nomilous this still doesn't work. I've had a similar problem. What works for my case is calling
|
@nomilous synchronous or cases returning a promise can also have a timeout. @andela-engmkwalusimbi this isn't supposed to work. As @boneskull wrote:
|
For everyone still wondering about this, ensure you understand what an arrow function implies, then come back here and read on (there are plenty of resources out there that can explain this far better than I can). The only way this arrow functions would work in this case is if we change the it('should do something', function (done) {
this.timeout(9000);
// stuff
done();
}); it'd look like this: it('should do something', (context, done) => {
context.timeout(9000);
done();
}); That'd would break every async Mocha test in existence, regardless if it was backwards-compatible otherwise: it('should do something', function (context, done) {
// context is unused, but 'done' is now the second parameter
this.timeout(9000);
done();
}); We could provide an alternative That's about the most thorough explanation I have of "where this issue is at". 😄 |
Maybe it could be taken into consideration for the next major version? I don't think it's an important enough change to create an alternative bdd implementation. Having named arguments might help with future development too and maybe create a simple way to add some kind of test middleware like so:
|
@boneskull A new bdd-es6 interface would be great :) |
Although I am in love with arrow functions which are really useful for e.g. Array functions like |
i'm unclear, is there a solution to timeout out a
Has no effect. still getting 4 second timeout here. This is the only slow thing in my test suite. I can put timeout to 30s in Here's how I solved it in the meantime (note that the first
|
I swear I read somewhere you could do something like this:
which doesn't alter the parameter contract to the provided function. Now I can't find any reference to any such thing so maybe I just imagined it. |
@thom-nic this works! i guess it makes sense since all of mocha's functions returns its context
|
It works with me when replacing the arrow function form with the normal function function() { ..... } |
Hi Folks. I apologize for going dark after sparking the discussion back in august, i've been quite busy and actually have mostly completed/moved-on from that work. I appreciate the detailed response about the different use cases and how its hard to dovetail them together. That was the most concise showing of the different setups mocha has to support that I've read. So thank you for your time on that one. Looking back, its clear that I must have over-emphasized getting access to mocha context ( Obviously, if I wanted to access the bound context I could simply use Ok So instead we write a function thats general enough to start the application code up with any potentially supported inputs, perform the test action, and then assert the results... Add that in my case I was working with the Promise abstraction (for reasons that i'll leave out), so this generalized test procedure function naturally has to return that promise.then chain. Bread and butter es6 kind of stuff, so far so good. Now comes the test scenarios, since we packed everything into our test-procedure function, the test cases are effectively defining the inputs and invoking the function. So perhaps I write a bunch of tests like this, and everything seems to be working:
If you're following along closely, you will have probably noticed already that this example has a bug. It is missing its The test should of course really look like this with a return:
Now I know this test is going to be one line in most cases. Actually, every case will be one line, except for when the inputs are such that a larger timeout is required. Now among the differences between classical js functions and arrows, there is a particular aspect of arrow functions that is useful here: a single statement arrow function has an implied return when braces are omitted. If instead of writing a Like so:
Now what if one of these cases takes longer than the others! We can of course set the timeout like this:
Or maybe someone will make a mistake and do this first (which doesn't work of course):
But now we're back where we started, the codebase has a pattern ripe for repeating, which is susceptible to the missing return bug (either by future me, or the next person to add a feature -- the point is, its an easy mistake to make, it may go unnoticed, and it can be hard to track down). The
(note, i wasn't able to get the Maybe there are linters that can flag missing returns-for-promise bugs (or probably more realistically, enforcing a return statement with a rhs for every function). However that wasn't an option at the time, plus I think the arrow syntax comes out shorter and I find it (subjectively/personally) easier to read and work with, which tipped the scales for me away from So there you have it. I don't know if I'll have time to respond again anytime soon, so I hope that was at least informative and clear, and maybe even puts some of the controversy surrounding the whole "access to mocha-context from arrows" stuff to bed. Lastly, since I found function vs => confusing for a long time, I'll drop this link in case its not clear to anyone casually reading why arrows can't access https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/ |
@thom-nic It works on describe('my test suite', () => {
it('test case 1', () => {
// ...
}).timeout('10s'); // Works on `it`. This test case doesn't timeout
it('test case 2', () => {
// ...
}); // This test case timeouts.
}).timeout('10s'); // Doesn't work on `describe`. Tests are already created when runs to here. |
@thom-nic , you may use the normal function form
|
Anyone complaining about this doesn't understand arrow functions. Arrow functions are NOT a new fancy ES6 thing is supposed to replace the classic Yes, even when using full ES6 syntax, you should still be using
|
Don't lambda functions also allow you to automatically send a single argument to the function without declaring it in the call? (param)=>aFunction function(){} can be bound to 'this' but ()=> is 'locked in' Arrow functions should replace the traditional function when the receiver expects a pre-determined 'this' in the same context that it is called from, (and also benefit from typing less code). I would go so far as to say never use function() unless you want 'this' to be something other than what 'this' is when invoking it. |
@Flamenco...
I'm not sure I understand exactly how you're putting that.
What you may have been getting at is that fat arrows allow you to return a value by omitting the curly braces and the
...and you wanted to convert that into a fat arrow function, you would not be able to shake the curly braces and the return keyword because the function body has multiple statements. You'd do it like this...
If, rather you started with...
...then you're dealing with a function that so simple that it just returns a single expression and you could use...
That got a lot easier to read! |
There are many different coding styles in JavaScript -- from OOP to FP, from strict type-safety to mixin/duck-typing. In addition, there are advanced patterns in each of those styles (i.e. dependency injection in OOP camp, currying/monad in the FP camp). If your coding style is closer to FP where Any experienced developer can just pre-wrap the testing framework to suit their coding style, but that means the framework is less "out-of-the-box". That translates to extra work for upgrading, adopting plugins, and onboarding new engineers. |
I like the idea of an alternative But it’s not so straightforward to implement, IIRC. Would be cool to see an attempt though. |
I know this is getting into serious side-effects land, but couldn't you deal with the done-or-context parameter something like this?
|
i used the below script but i got the same Timeout exceed error. Myscript : describe("getBillingDetail", async function (){ Error: Timeout of 55000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. |
Don't pass a done callback to an async function |
I've created a prototype solution that's backwards compatible. For now it's a separate module, but functionality could easily be merged into https://github.com/papercuptech/mocha-lambda quick wayrequire('mocha-lambda')
// now a global '_tst' can be used where 'this' was before
describe('suite', () => {
beforeEach(() => {
_tst.answer = 42
})
it('provides "this" as "_tst"', function() {
assert(this === _tst)
})
it('works', () => {
assert(_tst.answer === 42)
_tst.skip()
})
}) for explicit naming (and works with TypeScript)// if you were previously explicitly importing api (describe, it, etc.) from 'mocha',
// you will have to change to importing from 'mocha-lambda', until (or if) this
// gets merged into mocha proper
import ctx, {describe as d, it as i} from 'mocha-lambda'
d('suite', () => {
// ctx() is a function that returns "this" as appropriate
i('works using ctx()', () => {
ctx().skip()
})
})
import {Context} from 'mocha'
// ctx() can also rename global
ctx('t')
declare var t: Context
d('suite', () => {
// ctx() is a function that returns "this" as appropriate
i('works using renamed global', () => {
t.skip()
})
}) |
@papercuptech The link is 404 not found. |
Woops.. was private repo. now public Can also npm i mocha-lambda |
see @thom-nic answer, clean and did the trick |
@thom-nic solution worked for me, thanks! |
When using Node >= 4 with "use strict" and ES6 syntax for arrow functions, mocha fails:
Using ES5 syntax does work:
So, which kind of ugly trick does mocha with
this
?The text was updated successfully, but these errors were encountered: