Question

I'm trying to mock a backend for an app that I'm building using Angular JS.

I have the following code to mimic a successful request to log in:

// Login
$httpBackend.when('PUT','/v1/token/',{
    'domain'   : 'farmers',
    'username' : 'user',
    'password' : 'test'
}).respond({
    'token' : 'lalskdfjlskadjfklsadjf'
});

Of course this only works if I pass the exact object that I defined here.

I would like to know how I can change that to accept all PUT requests to /v1/token/ regardless of the dataset passed. It should then check whatever data is passed to see if it matches the structure illustrated above, and then return either the token or a failure message.

Is this possible?

Update: So I'm trying to get this working.. I've put a function as the param of the .respond() function, to try to anticipate different possible datasets being passed.

Javascript

// Login
$httpBackend.when('PUT','/v1/token/').respond(function (method, url, data, headers) {
    var validLogin = {
        'domain'   : 'farmers',
        'username' : 'user',
        'password' : 'test'
    };

    if ( data !== validLogin ) {
        return {
            result : 'fail'
        };
    } else {
        return {
            'token' : 'lalskdfjlskadjfklsadjf'
        };
    }
});

This doesn't work at all though. Now no matter what I pass, I get an undefined error:

undefined error in Chrome

Was it helpful?

Solution

I think that your continuing problems stem from what you're returning from your response method. This worked for me:

$httpBackend.when('PUT','/v1/token/')
.respond(function(method, url, data, headers) {
    var validLogin = {
      'domain'   : 'farmers',
      'username' : 'user',
      'password' : 'test'
    };

    if ( data !== JSON.stringify(validLogin)) {
        return [400, {failure: 'bad'}]
    } else {
        return [200, {token: '12345'}]
    } 
});

Notice how I'm returning an array of values (described in docs).

Working Plunker (test passes whether token is returned or not - you need to look at console)

OTHER TIPS

See the documentation for $httpBackend: https://docs.angularjs.org/api/ngMock/service/$httpBackend

You can use a function instead of an object to check the data, it will pass in a string. See below:

EDIT You need to put your "validData" matching logic in the data function, not the respond function...

// Login
$httpBackend.when('PUT','/v1/token/',function(dataString){
     var validLogin = {
        'domain'   : 'farmers',
        'username' : 'user',
        'password' : 'test'
     };

     var dataObject = JSON.parse(dataString);

     if (dataObject.username && dataObject.password && dataObject.domain) {
        return true;
     }
     else{
        return false;
     }
}).respond({
    'token' : 'lalskdfjlskadjfklsadjf'
});

The documentation suggests that it takes in a regular expression, so you can do something like this:

$httpBackend.when('PUT', /\/v1\/token\/[1-9][0-9]*/)

Of course, this is just an example. Create your own regular expressions to match.

You can use regular expressions, and the more in depth callback for respond to accomplish this. Here's an example of a fake API server:

$httpBackend.whenGET(/data.*/).respond(function(method, url, data, headers) {
    var query = url.split('?')[1],
        requestParams = {};

    var vars = query.split('&');
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        requestParams[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
    }

    for (var key in requestParams) {
        if (key.indexOf('[') >= 0) {
            var params = key.split(/\[(.*)\]/), value = requestParams[key], lastKey = '';

            angular.forEach(params.reverse(), function(name) {
                if (name != '') {
                    var v = value;
                    value = {};
                    value[lastKey = name] = isNumber(v) ? parseFloat(v) : v;
                }
            });
            requestParams[lastKey] =
                angular.extend(requestParams[lastKey] || {}, value[lastKey]);
        } else {
            requestParams[key] = 
                isNumber(requestParams[key]) ? parseFloat(requestParams[key]) : requestParams[key];
        }
    }

    var data = [ << a bunch of fake objects >> ];
    << do something to the data based on requestParams >>

    return [200, {
        result: data,
        total: data.length
    }];
});
$httpBackend.whenGET(/.*/).passThrough();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top