2
votes

I am using protractor for my e2e tests and jasmine2 as framework. I am using a plugin for html reporter with screenshots ( html-report for protractor ).

In these reports there will be shown a list of all failed/passed expects. When the expect fails I get a descriptive message of the expectation. However when the expect passes I only see the word: Passed. The reason behind that is that jasmine overrides the message when the expect passes.

That is done in the following file:

 node_modules/protractor/node_modules/jasmine/node_modules/jasmine-core/lib/jasmine-core/jasmine.js
getJasmineRequireObj().buildExpectationResult = function () {
    function buildExpectationResult(options) {
        var messageFormatter = options.messageFormatter || function () {
                },
            stackFormatter = options.stackFormatter || function () {
                };

        var result = {
            matcherName: options.matcherName,
            message: message(),
            stack: stack(),
            passed: options.passed
        };

        if (!result.passed) {
            result.expected = options.expected;
            result.actual = options.actual;
        }

        return result;

        function message() {
            if (options.passed) {
                // Here is the message overriden
                return 'Passed.';
            } else if (options.message) {
                return options.message;
            } else if (options.error) {
                return messageFormatter(options.error);
            }
            return '';
        }

        function stack() {
            if (options.passed) {
                return '';
            }

            var error = options.error;
            if (!error) {
                try {
                    throw new Error(message());
                } catch (e) {
                    error = e;
                }
            }
            return stackFormatter(error);
        }
    }

    return buildExpectationResult;
};

What I wanted is to override this function in my protractor protractor.conf.js file. And replace it with one with the desired behaviour.

I've tried to do so unsuccessfully doing the following:

onPrepare: function () {
    jasmine.buildExpectationResult = function () {
        function buildExpectationResult(options) {
            var messageFormatter = options.messageFormatter || function () {
                    },
                stackFormatter = options.stackFormatter || function () {
                    };

            return {
                matcherName: options.matcherName,
                expected: options.expected,
                actual: options.actual,
                message: message(),
                stack: stack(),
                passed: options.passed
            };

            function message() {
                if (options.message) {
                    return options.message;
                } else if (options.error) {
                    return messageFormatter(options.error);
                }
                return "";
            }

            function stack() {
                if (options.passed) {
                    return "";
                }

                var error = options.error;
                if (!error) {
                    try {
                        throw new Error(message());
                    } catch (e) {
                        error = e;
                    }
                }
                return stackFormatter(error);
            }
        }

        return buildExpectationResult;
    };
} 

Then my questions is: What is the right way to override a jasmine method?

2

2 Answers

0
votes

Since we use gulp task to run protractor tests, we override the lib (like jasmine lib) as one of the gulp task with custom copy. We do that as part of installation or every test execution.

I didn't find any good way to override it unless we create another npm module.

0
votes

I had the same issue, I'm not sure if my solution

onPrepare: function () {
// ...
jasmine.Spec.prototype.addExpectationResult = function(passed, data, isError) {
  var buildExpectationResult = function(options) {
      var messageFormatter = options.messageFormatter || function() {},
        stackFormatter = options.stackFormatter || function() {};
  
      var result = {
        matcherName: options.matcherName,
        message: message(),
        stack: stack(),
        passed: options.passed
      };
  
      if(!result.passed) {
        result.expected = options.expected;
        result.actual = options.actual;
      }
  
      return result;
  
      function message() {
        if (options.passed) {
          return options.message ? options.message : 'Passed';
        } else if (options.message) {
          return options.message;
        } else if (options.error) {
          return messageFormatter(options.error);
        }
        return '';
      }
  
      function stack() {
        if (options.passed) {
          return '';
        }
  
        var error = options.error;
        if (!error) {
          try {
            throw new Error(message());
          } catch (e) {
            error = e;
          }
        }
        return stackFormatter(error);
      }
    }

  var exceptionFormatter = jasmine.ExceptionFormatter;

  var expectationResultFactory = function(attrs) {
    attrs.messageFormatter = exceptionFormatter.message;
    attrs.stackFormatter = exceptionFormatter.stack;

    return buildExpectationResult(attrs);
  }

  var expectationResult = expectationResultFactory(data);

  if (passed) {
    this.result.passedExpectations.push(expectationResult);
  } else {
    this.result.failedExpectations.push(expectationResult);

    if (this.throwOnExpectationFailure && !isError) {
      throw new j$.errors.ExpectationFailed();
    }
  }
};

// ...
}