16

When I make an API call I want to inspect the returned JSON for its results. I can see the body and some the static data is being checked properly, but wherever I use regular expression things are broken. Here is an example of my test:

describe('get user', function() {

    it('should return 204 with expected JSON', function(done) {
      oauth.passwordToken({
        'username': config.username,
        'password': config.password,
        'client_id': config.client_id,
        'client_secret': config.client_secret,
        'grant_type': 'password'
      }, function(body) {
        request(config.api_endpoint)
        .get('/users/me')
        .set('authorization', 'Bearer ' + body.access_token)
        .expect(200)
        .expect({
          "id": /\d{10}/,
          "email": "qa_test+apitest@example.com",
          "registered": /./,
          "first_name": "",
          "last_name": ""
        })
        .end(function(err, res) {
          if (err) return done(err);
          done();
        });
      });
    });
  });

Here is an image of the output:

enter image description here

Any ideas on using regular expression for pattern matching the json body response?

Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297
Daniel
  • 293
  • 4
  • 8

4 Answers4

7

There are two things you may consider in your tests: your JSON schema and the actual returned values. In case you're really looking for "pattern matching" to validate your JSON format, maybe it's a good idea to have a look at Chai's chai-json-schema (http://chaijs.com/plugins/chai-json-schema/).

It supports JSON Schema v4 (http://json-schema.org) which would help you describe your JSON format in a more tight and readable way.

In this question's specific case, you could use a schema as follows:

{
    "type": "object",
    "required": ["id", "email", "registered", "first_name", "last_name"]
    "items": {
        "id": { "type": "integer" },
        "email": { 
            "type": "string",
            "pattern": "email"
        },
        "registered": { 
            "type": "string",
            "pattern": "date-time"
        },
        "first_name": { "type": "string" },
        "last_name": { "type": "string" }
    }

}

And then:

expect(response.body).to.be.jsonSchema({...});

And as a bonus: the JSON Schema supports regular expressions.

Gustavo Meira
  • 2,875
  • 3
  • 21
  • 33
6

I asked this question early in my understanding of the framework. For anyone else who stumbles on this, I recommend using chai for assertion. This helped use regular expression for pattern matching in a much cleaner way.

Here is an example:

res.body.should.have.property('id').and.to.be.a('number').and.to.match(/^[1-9]\d{8,}$/);
Daniel
  • 293
  • 4
  • 8
4

I wrote lodash-match-pattern and it's Chai wrapper chai-match-pattern to handle just these sorts of assertions. It can handle what you described with regular expressions:

chai.expect(response.body).to.matchPattern({
  id: /\d{10}/,
  email: "qa_test+apitest@example.com",
  registered: /./,
  first_name: "",
  last_name: ""
});

or use any of many included matchers and potentially ignore fields that don't matter

chai.expect(response.body).to.matchPattern({
  id: "_.isInRange|1000000000|9999999999",
  email: _.isEmail,
  registered: _.isDateString,
  "...": ""
});
mjhm
  • 16,497
  • 10
  • 44
  • 55
0

I think chai uses excessively verbose syntax.

var assert = require('assert');
        //...
        .expect(200)
        .expect(function(res) {
            assert(~~res.body.id);
        })
        //...
Lee Goddard
  • 10,680
  • 4
  • 46
  • 63
evgenAborigen
  • 175
  • 1
  • 7