calling ramda compose in nodejs class

265 Views Asked by At

I have the following method skipLoggingThisRequest in a node js class which I am trying to test. The method is supposed to return either true or false, based on the path in request, using ramda compose to get to that value. However in my tests, no matter what path I set in the request object, my skipLoggingThisRequest always returns true.

What am I missing here?

my class:

import { compose, filter, join, toPairs, map, prop, flip, contains, test, append } from 'ramda'
import { create, env } from 'sanctuary'
import { isEmpty, flattenDeep } from 'lodash'
import chalk from 'chalk'
import log from 'menna'

class MyClass {

    constructor (headerList) {
        this.headerWhiteList = flattenDeep(append(headerList, []));
    }

    static getBody (req) {
        return (!isEmpty(req.body) ? JSON.stringify(req.body) : '');
    }

    static S () {
        return create({ checkTypes: false, env });
    }

    static isInList () {
        return flip(contains);
    }

    static isInWhitelist () {
        return compose(this.isInList(this.headerWhiteList), this.S.maybeToNullable, this.S.head);
    }

    static parseHeaders () {
        return (req) => compose(join(','), map(join(':')), filter(this.isInWhitelist), toPairs, prop('headers'));
    }

    skipLoggingThisRequest () {
        return (req) => compose(test(/^.*(swagger|docs|health).*$/), prop('path'))
    }

    logger (req, res, next) {
        if (this.skipLoggingThisRequest(req)) {
            console.log('Skipping')
            return next();
        }

        const primaryText = chalk.inverse(`${req.ip} ${req.method} ${req.originalUrl}`);
        const secondaryText = chalk.gray(`${this.parseHeaders(req)} ${this.getBody(req)}`);
        log.info(`${primaryText} ${secondaryText}`);

        return next();
    }
}

export default MyClass

My tests:

import sinon from 'sinon';
import MyClass from '../lib/MyClass';

describe('MyClass', () => {
    const headerList = ['request-header-1', 'request-header-2'];

    const request = {
        'headers': {
            'request-header-1': 'yabadaba',
            'request-header-2': 'dooooooo'
        },
        'ip': 'shalalam',
        'method': 'GET',
        'originalUrl': 'http://myOriginalUrl.com',
        'body': ''
    };
    const response = {};

    const nextStub = sinon.stub();

    describe('Logs request', () => {
        const myInstance = new MyClass(headerList);
        const skipLogSpy = sinon.spy(myInstance, 'skipLoggingThisRequest');
        request.path = '/my/special/path';
        myInstance.logger(request, response, nextStub);
        sinon.assert.called(nextStub);
    });
});
1

There are 1 best solutions below

0
On

this.skipLoggingThisRequest(req) returns a function ((req) => compose(test(/^.*(swagger|docs|health).*$/), prop('path'))).

It does not return a boolean. However, since functions are truthy, your if statement always executes.

What you most likely want to do is this.skipLoggingThisRequest()(req). You get the function and then apply a request to it.

Demonstration of what's going on:

const testFunction = () => (test) => test === "Hello!";
console.log(testFunction);
console.log(testFunction());
console.log(testFunction()("Hello!"));
console.log(testFunction()("Goodbye!"));

if (testFunction) {
  console.log("testFunction is truthy.");
}

if (testFunction()) {
  console.log("testFunction() is truthy.");
}

if (testFunction()("Hello!")) {
  console.log('testFunction()("Hello!") is truthy.');
}

if (!testFunction()("Goodbye!")) {
  console.log('testFunction()("Goodbye!") is falsey.');
}