xyhhx
xyhhx

Reputation: 6674

Capture varied requests with $httpBackend

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

Upvotes: 1

Views: 1551

Answers (4)

Marc Kline
Marc Kline

Reputation: 9409

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)

Upvotes: 4

Andrew Church
Andrew Church

Reputation: 1391

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'
});

Upvotes: 2

mbroadst
mbroadst

Reputation: 888

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();

Upvotes: 0

Ishan Chatterjee
Ishan Chatterjee

Reputation: 835

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.

Upvotes: 0

Related Questions