I am trying to implement a custom matcher for Jasmine where I would like to check if the given object property values lie within the range of the other two object property values.

Here is what I got so far:

let matcher = {
            toLieWithin: function (util: jasmine.MatchersUtil, customEqualityTesters: Array<jasmine.CustomEqualityTester>): jasmine.CustomMatcher {
                return {
                    compare: function (actual: any, expected: any): jasmine.CustomMatcherResult {
                        let result: jasmine.CustomMatcherResult = {
                            pass: false,
                            message: ''
                        };

                        result.pass = liesWithin(actual, expected);

                        return result;
                    }
                }
            }
        }; 

function liesWithin<T>(objActual: T, objExpected: T[]): boolean {
        let output: boolean;
        if(objExpected) {
          output = objActual.x > objExpected[0].x && objActual.x < objExpected[1].x && objActual.y > objExpected[0].y && objExpected[1].y;
        }
return output;    
}

Here, I am assuming, the actual has two properties x and y. And the expected is an array of two objects which also has two properties each x and y.

actual = {x: -5, y: -10}; expected = [{x: -10, y: -17},{x: 0, y: 0}];

Now, this scenario works I believe for the above given simple example. But when I am trying to implement it as a generic, how do I find what properties does the object have? And is my approach correct? Could anyone give me some ideas how can I implement such a method.

Thank you.

1

There are 1 answers

3
Murad Khan On BEST ANSWER

It looks like you're on the right track with your liesWithin function, you just need to account for the situation where the expected object may not come back ordered how you expect. This code should cover those situations as well:

// Helper to reduce repeated code
function isWithinRange(val, a, b) {
    return (val > a && val < b) || (val > b && val < a);
}

function liesWithin<T>(objActual: T, objExpected: T[]): boolean {
    if (objExpected) {
        let props = Object.keys(objActual);
        // Splitting X and Y checks into two for readability
        let isInYRange = isWithinRange( objActual[ props[0] ], objExpected[0][ props[0] ], objExpected[1][ props[0] ] );
        let isInXRange = isWithinRange( objActual[ props[1] ], objExpected[0][ props[1] ], objExpected[1][ props[1] ] );
        return isInXRange && isInYRange;
    }
    return;
}