2

I have a string that is used to display text. It is initially set to null, then is updated throughout a function with status updates. I want to make sure the string is set to the correct status updates throughout the function's lifetime.

Jasmine's spies seem focused on testing functions and their interactions. I specifically want to test a string's history. Assuming the following code:

(function() {
    $this.loggingIn = false;

    $this.submit = function () {
        $this.loggingIn = "Requesting access...";
        $this.errorMessage = "";
        var aThing = {};
        var aSecondaryThing = {};

        $http.post(aThing)
            .success(function (data, status, headers, config) {

                $this.loggingIn = "Validating credentials...";

                $http.post(aSecondaryThing)
                    .success(function (data, status, headers, config) {
                        $this.loggingIn = "Done!";
                    })
                    .error(function (data, status, headers, config) {
                        $this.errorMessage = data.error_description || "Invalid username or password.";
                        $this.loggingIn = false;
                    });
            })
            .error(function (data, status, headers, config) {
                $this.errorMessage = data.error_description || "Invalid username or password.";
                $this.loggingIn = false;
            });

            return false;
    };
})();

This function is abridged from our original Angular code. Nothing's missing aside from the wiring to make the controller work and the post actions.

Is there a way to test that loggingIn is set to "Validating credentials..." and then "Done!" without writing a setter function to handle it?

Codeacula
  • 2,329
  • 25
  • 30
  • Hm. This is an interesting question. I don't think Jasmine has a way of spying on getter and setting properties in JavaScript. – Greg Burghardt Jul 09 '15 at 15:14
  • Related, but not duplicate: [How to spyOn a value property (rather than a method) with Jasmine](http://stackoverflow.com/questions/20879990/how-to-spyon-a-value-property-rather-than-a-method-with-jasmine) – Greg Burghardt Jul 09 '15 at 15:14
  • I saw that one and want sure if it was what I was looking for normally, then realized they're talking about an object. Close! – Codeacula Jul 09 '15 at 15:19
  • Another related question: [Mocking HTTP service unit test with AngularJS and Jasmine](http://stackoverflow.com/questions/27174673/mocking-http-service-unit-test-with-angularjs-and-jasmine). It's not a duplicate in my opinion because you want to verify the behavior of the controller within the AJAX lifecycle. – Greg Burghardt Jul 09 '15 at 15:24
  • Maybe you could mock the `$http` object using the [$httpBackend](https://docs.angularjs.org/api/ngMock/service/$httpBackend) provided by Angular, have it return a stub promise. Then your unit test could assert that `loggingIn` is one value, then call the `success` method and make another assertion? – Greg Burghardt Jul 09 '15 at 15:25
  • I have a solution already. I wrote a setter function to test against. But I wanted to know if I really needed to do this or not. JavaScript is a magical language. – Codeacula Jul 09 '15 at 15:27
  • I think in this one particular instance, you don't need to verify that "Validating credentials..." shows up on screen. The end result of logging in is more important. I wrote a JavaScript mocking library for AJAX called [Mocking Bird](https://github.com/gburghardt/mocking_bird) that might interest you. You can create a "Delayed Builder Mock" so your unit test can control the AJAX life cycle in a fine grained fashion. You could use the normal `$http` object in Angular. I just haven't tried it with Angular yet. – Greg Burghardt Jul 09 '15 at 15:43
  • It's a requirement to have the messages display in a certain order, thus the testing. Not so much "is it needed" but "can it be done." – Codeacula Jul 09 '15 at 15:46
  • I think it can be done if the `$http.post` method can return a mock promise. Then your unit test can call `success` or `error` and make the proper assertions. – Greg Burghardt Jul 09 '15 at 15:55
  • Cleaned it up. I think you're right, there's no real way to test the string without a setter function handling it. If you'd like to put it as an answer, I'll accept it after I give others some time (in case someone comes in and wows us both) – Codeacula Jul 09 '15 at 16:02

1 Answers1

0

Ultimately we went with a setter function to handle the string management and testing. Although testing what the string actually says probably isn't needed, at the time it was required enough to need verification. That way we can verify if the function was being called, and then later verify the function changes the string correctly, which is proper testing in any case.

Codeacula
  • 2,329
  • 25
  • 30