Extending Supertest

DateReadtime 3 minutes Series Part 1 of Testing Express Tags

I have an express app running behind an Apache reverse proxy with mod_auth_mellon used to authenticate users via SAML.

As a result of relying on headers for auth, I have lots of mocha tests that look like:

it("should add a comment with a user", (done) => {
    let expectedUser = "a User";
    let commentRequest = { ... };

    request(app)
        .post("/comment")
        .set("oidc_claim_sub", "aRemoteUser")
        .set("oidc_claim_name", "John Doe")
        .set("oidc_claim_email", "jdoe@example.com")
        .set("oidc_claim_iss", "anIdentityProvider")
        .send(commentRequest)
        .expect(200)
        .end(function (error, response) {
            assert.equal(response.body.user.name, expectedUser, "user name did not match");
            if (error) {
                return done(error);
            }
            done();
        });
});

I wanted to extend supertest to allow a helper that would reduce duplication in test setup code and silly mistakes. I was hoping for something more like:

request(app)
    .post("/comment")
    .authenticate()

It turns out that supertest provides a Test constructor that can be extended. So a simple header can be written like so:

function addRequestWithAuthHeaders(request) {
    let Test = request.Test;

    Test.prototype.authenticate = function(options = {}) {
        return this
            .set("oidc_claim_sub", options["subject"] || "aRemoteUser")
            .set("oidc_claim_name", options["name"] || "John Doe")
            .set("oidc_claim_email", options["email"] || "jdoe@example.com")
            .set("oidc_claim_iss", options["issuer"] || "anIdentityProvider")
    }
}

Voila!

describe("when routed to", () => {
     var app;

     beforeEach(() => {
         app = express();
         app.use(bodyParser.json());
         app.use(router);

         helpers.addRequestWithAuthHeaders(request);
     });

     it("should add a comment with a user", (done) => {
         let expectedUser = "a User";
         let commentRequest = { ... };

         request(app)
             .post("/comment")
             .authenticate()
             .send(commentRequest)
             .expect(200)
             .end(function (error, response) {
                 assert.equal(response.body.user.name, expectedUser, "user name did not match");
                 if (error) {
                     return done(error);
                 }
                 done();
             });
     });
 });
source:https://github.com/visionmedia/supertest/issues/381