[Update]
FuncUnit
provides the functionality I require and has solved this problem for me.
I am writing a suite of tests for the UI of an audio player and
need to wait until the side-effect of one UI event is seen by another
UI element.
Ideally I'd like to "wait until a
UI element is is a prticular state" but for the moment I am
"allowing a reasonable time for the side-effect to happen".
The problem is with setTimeout and is that, if the
browser's threads are not "hot" - as it were - the tests
will usually fail due to steps being run in either the wrong order or
too close together in time. Indeed, according to
Mozilla
MDN "It's important to note that the function or code
snippet cannot be executed until the thread that called setTimeout()
has terminated."
By "hot browser threads"
I mean that a first refresh of the page will produce false test
negatives but a second page refresh will have all the tests passing.
I'd be very grateful for any advice on how others
approach what must be a reasonably common QUnit use case.
I thought this would be the best place to come for some extra
light! The test below works .... but only after a first page refresh
produces false negatives; a secong page refresh passes all the
assertions. Not suitable for an outomated test then!
Ideally I would like to "wait for a UI element to be in an
asserted state" but for the moment, until I understand the QUnit
+ Javascript threading model better my approach is to "wait for a
reasonable amount of time for one UI element to see the side-effect of
another UI action`'.
- //
Not entirely satisfactory since you have to run the test suite
more than once to achieve sufficent response from the
browser.
- QUnit.test(
-
'play sequence: mute button sets volume slider to zero and
toggle remembers previous volume' ,
-
function ( assert ) {
-
var play_button = $('.playa > section >
button:first-child');
-
var seek_slider = $('.playa > section > div >
input');
-
var mute_button = $('.playa
button.btn:nth-child(4)');
-
var volume_slider = $('.playa div.btn:nth-child(5) >
input:nth-child(1)');
-
var delay = 1000; // milliseconds
-
var volume_level = '0.13';
-
-
// quiet: we're testing
-
volume_slider.val(volume_level);
-
volume_slider.trigger('change');
-
-
// wait for the volume slider's round-trip side-effect
-
// mute button is notified by an audio volumechange
-
var done_1 = assert.async();
-
setTimeout(function() {
-
play_button.trigger('click');
-
done_1();
-
-
// wait for the play button's riund-trip side-effect
-
// seek slider is notified by audio.currentTime
-
var done_2 = assert.async();
-
setTimeout(function() {
-
play_button.trigger('click'); // stop play
-
assert.ok( seek_slider.val() > '0', 'volume in
non-zero position after pause');
-
mute_button.trigger('click'); // mute
-
assert.ok( true, 'mute button clicked (to mute) after volume
slider checked' );
-
done_2();
-
-
// wait for the mute button to have a round-trip effect on the
volume slider
-
var done_3 = assert.async();
-
setTimeout(function() {
-
assert.equal( volume_slider.val(), '0', 'mute button
sets volume slider to zero' );
-
mute_button.trigger('click'); // unmute
-
assert.ok( true, 'mute button clicked (to UN-mute) after
volume slider checked' );
-
done_3();
-
-
// again, wait for the mute button to have a round-trip effect on
the volume slider
-
var done_4 = assert.async();
-
setTimeout(function() {
-
assert.equal( volume_slider.val(), volume_level, 'volume has
been restored' );
-
done_4();
-
}, delay); // wait this long before calling the function
above
-
}, delay); // wait for slider to adjust
-
}, delay); // wait for the audio to play for a mo
-
}, delay); // wait this long before pressing the pause
button
- });