views:

197

answers:

3

Help with unit testing checkbox behavior. I have this page:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="../js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript">
        $(function() {
            $('<div><input type="checkbox" name="makeHidden" id="makeHidden" checked="checked" />Make Hidden</div>').appendTo('body');
            $('<div id="displayer" style="display:none;">Was Hidden</div>').appendTo('body');

            $('#makeHidden').click(function() {
                var isChecked = $(this).is(':checked');

                if (isChecked) {
                    $('#displayer').hide();
                }
                else {
                    $('#displayer').show();
                }
                return false;
            });

        });

    </script>
</head>
<body>
</body>
</html>

This doesn't work it is because of the return false; in the click handler. If I remove it it works great. The problem is if I pull the click function out into it's own function and unit test it with qunit it will not work without the return false;

[EDIT] Using @patrick's answer my results are:

Firefox:

  • Manual test of toy - good.
  • Unit Tests - good.
  • Manual test of production app - good.

Internet Explorer:

  • Manual test of toy - fail.
  • Unit Tests - good.
  • Manual test of production app - fail.

Internet Explorer requires initially, one-click. after that it requires two clicks.

I thought jQuery is to abstract away browsers?

Am I going to have to override the entire check box behavior for a solution?

In my unit tests this is how I am doing the check box simulation of a user:

$(':input[name=shipToNotActive]').removeAttr('checked');
$('#shipToNotActive').change();

and also:

$(':input[name=shipToNotActive]').attr('checked', 'checked');
$('#shipToNotActive').change();
A: 

Try this:

$(function() {
    $('<div><input type="checkbox" name="makeHidden" id="makeHidden" checked="checked" />Make Hidden</div>').appendTo('body');
    $('<div id="displayer" style="display:none;">Was Hidden</div>').appendTo('body');

    $('#makeHidden').click(function() { return onCheckboxClicked(this) } );
});

function onCheckboxClicked(el) {
    var isChecked = $(el).is(':checked');

    if (isChecked) {
        $('#displayer').hide();
    }
    else {
        $('#displayer').show();
    }
    return false;
}
Coronatus
been down this road. becuase of the return false it overrides the behavior of the checkbox. It will always be checked. it does run the click though, but then resets the checked property internally on the checkbox. really retarded. happens in ie and firefox
Gutzofter
+2  A: 

How about using change instead of click?

$('#makeHidden').change(function() {
            var isChecked = $(this).is(':checked');

            if (isChecked) {
                $('#displayer').hide();
            }
            else {
                $('#displayer').show();
            }
            return false;
        });

The return false; won't be in the way since the event is fired as a result of the change having occurred.

patrick dw
This works so far in my toy example. now let me run my tests in real code!
Gutzofter
Sounds good. Let me know how it turns out.
patrick dw
Works like a charm in Firefox. Firefox: Manual test of toy - good. Unit Tests - good. Manual test of production app - good.Internet Explorer: Manual test of toy - fail. Unit Tests - good. Manual test of production app - fail.Internet Explorer requires initially, one-click. after that it requires two clicks.
Gutzofter
I love IE. Sorry to say, I don't have a clue. Tinkered for a while, and don't know how to make it behave.
patrick dw
see my hack to the question.
Gutzofter
+1  A: 

Here is a work around.

Now my code is like this:

        if ($.browser.msie) {
            $('#makeHidden').change(function () {
                this.blur();
                this.focus();
                onCheckboxClicked();
            });
        }
        else {
            $('#makeHidden').change(function() {
                return onCheckboxClicked();
            });
        }

All my tests including manual toy and manual production are good.

Anybody have something better than this hack?

Gutzofter
+1 - Interestingly, I worked on a somewhat similar IE `change` issue recently, except on a `select` list. That solution/hack required a native API `blur()` and `focus()` like yours. Unlike yours, that issue was with `change` *not* firing the first time, yet the second change (and every change thereafter) fired. So the solution was a jQuery `focus()`, then a native `blur() focus()`. Thankfully, no browser check was necessary as the hack ran only once. I'm tracking this one as a reminder. Thanks for posting your solution.
patrick dw
The problem is that my unit tests didn't capture the problem. I think that is why you shouldn't test the gui.
Gutzofter