jspec.timers.js issue

3 views
Skip to first unread message

Mark Nijhof

unread,
Apr 17, 2010, 7:27:07 PM4/17/10
to js...@googlegroups.com
Hi,

I have some behavior that I think is wrong, when I have f.ex. the
following specification:

describe 'FeedBack'
before_each
div = elements('<div/>')
end

after_each
end

describe 'displaySuccessMessage(text, callBack)'
it 'will be able to use jQuery syntax'
$(div).displaySuccessMessage('test', null)
true.should.be_true
end

it 'will append a div with the message'
$(div).displaySuccessMessage('test', null)
$(div).html().should.match /^<div id=\"displaySuccessMessage\"
class=\"success\".*>test<\/div>$/
end

it 'will return the original object so it is chainable'
$(div).displaySuccessMessage('test', null).html().should.match
/^<div id=\"displaySuccessMessage\" class=\"success\".*>test<\/div>$/
end

it 'will be hidden at first'
$(div).displaySuccessMessage('test',
null).find('div').css('display').should.be "none"
end

it 'will be visible after 500 milliseconds'
tick(10)
$(div).displaySuccessMessage('test',
null).find('div').css('display').should.be "block"
end

end
end

And implementation:

(function($){

$.fn.displaySuccessMessage = function(messageText, callBack){
var $this = this;
$this.html('');
$this.append("<div id=\"displaySuccessMessage\" class=\"success\"
style=\"\">"+ messageText +"</div>");
$this.find('#displaySuccessMessage').css('display', 'none');

setTimeout(function(){
console.log($this.find('#displaySuccessMessage').css('display'));
$this.find('#displaySuccessMessage').fadeIn(400);
console.log($this.find('#displaySuccessMessage').css('display'));
}, 10);

return this;
};

})(jQuery);

Then the 'will be visible after 500 milliseconds' will fail, but when
you look at the console then you can clearly see that the timeout has
been triggered. The other weird thing is that this timeout is being
triggered for each test in the file. So not just for the tests that
have the tick() set for the right value. I would have assumed that
each test would be scoped individually?

Just to check if it had anything to do with the timer I also tried
this instead with the same results:
http://monket.net/blog/wp-content/uploads/2009/07/jsUnitMockTimeout.js

But when I move the $(div).displaySuccessMessage('test', null) into
the before_each then the scoping seems to be ok.

And one last thing is when using fadeIn or something like that then
nothing works anymore, is there a trick around that? How can the
callback for the fadeIn and fadfeOut type of functions be called? This
one is actually a nasty one which would prevent me from testing most
of the functionality.

-Mark



--
Mark Nijhof
Cre8ive Thought
m: 0047 95 00 99 37
e: mark....@cre8ivethought.com
w: www.cre8ivethought.com

--
JSpec thanks you for your interest and support! To post simply reply
to this email.

documentation: http://jspec.info
unsubscribe: jspec+un...@googlegroups.com
group: http://groups.google.com/group/jspec

Mark Nijhof

unread,
Apr 17, 2010, 8:34:43 PM4/17/10
to js...@googlegroups.com
Hey guys,

What do you think of this, for mocking the fadeIn and fadeOut:

(function($){

$.fn.___fadeIn = $.fn.fadeIn;
$.fn.fadeIn = function(duration, callBack){
var ___this = this;
setTimeout(function(){
___this.___fadeIn(0);
if (callBack != undefined)
callBack();
}, duration);
return this;
};

$.fn.___fadeOut = $.fn.fadeOut;
$.fn.fadeOut = function(duration, callBack){
var ___this = this;
setTimeout(function(){
___this.___fadeOut(0);
if (callBack != undefined)
callBack();
}, duration);
return this;
};

})(jQuery);

The duration stays the same as well as the actual end behavior, the
only thing is that this now works very nicely with the mocking of the
setTimeout, also take a look at the previous link I included for the
method runFunctionsWithinRange as this is very helpful as well, now I
can do this (instead of having to do multiple ticks):

it 'will be visible after 500 milliseconds'
Clock.runFunctionsWithinRange(0, 500)
$(div).find('#displaySuccessMessage').css('display').should.be "block"
end

it 'will stay visible for 3000 milliseconds'
Clock.runFunctionsWithinRange(500, 3500)
$(div).find('#displaySuccessMessage').css('display').should.be "block"
end

it 'will be hidden after 4000 milliseconds'
Clock.runFunctionsWithinRange(3500, 4000)
$(div).find('#displaySuccessMessage').css('display').should.be "none"
end

Cheers,

-Mark

tjholowaychuk

unread,
Apr 19, 2010, 2:55:29 PM4/19/10
to jspec
so you tried it with Pivotal's mock timers and got the issue as well?
or
did you find a bug in mock-timers?

On Apr 17, 5:34 pm, Mark Nijhof <mark.nij...@cre8ivethought.com>
wrote:
> > e:  mark.nij...@cre8ivethought.com
> > w:www.cre8ivethought.com
>
> --
> Mark Nijhof
> Cre8ive Thought
> m: 0047 95 00 99 37
> e:  mark.nij...@cre8ivethought.com

Mark Nijhof

unread,
Apr 19, 2010, 3:13:48 PM4/19/10
to js...@googlegroups.com
No I don't think it is in the mock timer, an animation is a chain of
timers or an interval (haven't looked at the jQuery source yet). So
instead of using that I replace the implementation with what I wrote
down in the previous mail. Then it is only one timer and that works
fine. Can you successfully check that what after an animation should
happen?

I also noticed something that I didn't think of before, but if your
code is checking for is(':visible') then that will not work even when
using the browser, because all tests are hidden :)

-Mark
e: mark....@cre8ivethought.com

vision media [ Tj Holowaychuk ]

unread,
Apr 19, 2010, 3:47:08 PM4/19/10
to js...@googlegroups.com
I used to have it a different way, so that might be a bug now lol I think it works
fine in the JSpec core specs though. hmm...
--
Tj Holowaychuk
Vision Media
President & Creative Lead

Mark Nijhof

unread,
Apr 19, 2010, 3:49:02 PM4/19/10
to js...@googlegroups.com
I can try to create a test that fails, try in a hour or so

Sent from my iPad Mini

vision media [ Tj Holowaychuk ]

unread,
Apr 19, 2010, 3:51:54 PM4/19/10
to js...@googlegroups.com
I know what you mean though, its supposed to check parents
and see if they are visible

Mark Nijhof

unread,
Apr 19, 2010, 5:32:52 PM4/19/10
to js...@googlegroups.com
I have been looking into the code a bit more and I think that the
timers are actually not at fault, but that it is the visibility stuff
instead. It just looked like the timers as I could only verify that it
worked by checking the display attributes on the element under test.
In order for slideUp for me to work I had to add a custom display:
block or display: none on there as well.

$.fn.___slideUp = $.fn.slideUp;
$.fn.slideUp = function(duration, callBack){
var ___this = $(this);
setTimeout(function(){
___this.___slideUp(0);
___this.css('display', 'none'); // Added because it will always
be hidden, since the tests are not shown
if (callBack != undefined)
callBack();
}, duration);
return this;
};

$.fn.___slideDown = $.fn.slideDown;
$.fn.slideDown = function(duration, callBack){
var ___this = $(this);
setTimeout(function(){
___this.___slideDown(0);
___this.css('display', 'block'); // Added because it will always
be hidden, since the tests are not shown
if (callBack != undefined)
callBack();
}, duration);
return this;
};

Is this visibility thing hard to fix? I would love to get that fixed!
Other then that I love JSpec!

Cheers,

-Mark

On Mon, Apr 19, 2010 at 9:51 PM, vision media [ Tj Holowaychuk ]

vision media [ Tj Holowaychuk ]

unread,
Apr 19, 2010, 6:05:06 PM4/19/10
to js...@googlegroups.com
i cant remember how i used to have it. jQuery used to just check dimensions, "display", and "visible" I think

Mark Nijhof

unread,
Apr 19, 2010, 6:07:01 PM4/19/10
to js...@googlegroups.com
Hehe I hope you had it under source control then, perhaps it is
findable? Can you reproduce it?

-Mark


On Tue, Apr 20, 2010 at 12:05 AM, vision media [ Tj Holowaychuk ]

vision media [ Tj Holowaychuk ]

unread,
Apr 19, 2010, 6:31:19 PM4/19/10
to js...@googlegroups.com
yup it is lol no worries. I wont have time to look at it today though
Reply all
Reply to author
Forward
0 new messages