From 32168be6c7ecf6b8f2d5a55e994263155ee2855f Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 22 Nov 2025 09:44:54 -0800 Subject: [PATCH] Statically expose pretty printer as jasmine.pp Pretty printing is occasionally useful outside of the places where a configured pretty printer is injected (matchers and asymmetric equality testers). Users sometimes use the private basicPrettyPrinter for that. jasmine.pp is part of the public interface and uses the current runable's custom object formatters. --- lib/jasmine-core/jasmine.js | 24 +++++++++++++++++++++++- spec/core/integration/EnvSpec.js | 28 ++++++++++++++++++++++++++++ src/core/Env.js | 7 +++++++ src/core/matchers/matchersUtil.js | 2 +- src/core/requireInterface.js | 15 +++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index e12541fa..7202fed7 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2045,6 +2045,13 @@ getJasmineRequireObj().Env = function(j$) { } }; + this.pp = function(value) { + const pp = runner.currentRunable() + ? runableResources.makePrettyPrinter() + : j$.private.basicPrettyPrinter; + return pp(value); + }; + this.cleanup_ = function() { uninstallGlobalErrors(); }; @@ -5288,7 +5295,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { this.customTesters_ = options.customTesters || []; /** * Formats a value for use in matcher failure messages and similar contexts, - * taking into account the current set of custom value formatters. + * taking into account the current set of custom object formatters. * @function * @name MatchersUtil#pp * @since 3.6.0 @@ -9500,6 +9507,21 @@ getJasmineRequireObj().interface = function(jasmine, env) { return env.setDefaultSpyStrategy(defaultStrategyFn); }; + /** + * Formats a value for display, taking into account the current set of + * custom object formatters. + * + * @name jasmine.pp + * @function + * @since 6.0.0 + * @param {*} value The value to pretty-print + * @return {string} The pretty-printed value + * @see {MatchersUtil#pp} + */ + jasmine.pp = function(value) { + return env.pp(value); + }; + /** * {@link AsymmetricEqualityTester|Asymmetric equality testers} allow for * non-exact matching in matchers that use Jasmine's deep value equality diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 5aa93a55..b6d9e320 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -3842,6 +3842,34 @@ describe('Env integration', function() { }); }); + describe('pp', function() { + it("pretty-prints using the current runable's custom object formatters", async function() { + env.it('a spec', function() { + env.addCustomObjectFormatter(function(x) { + if (x === 1) { + return 'hi!'; + } + }); + env.expect(env.pp(1)).toEqual('hi!'); + }); + + const reporter = jasmine.createSpyObj('reporter', ['specDone']); + env.addReporter(reporter); + + await env.execute(); + + expect(reporter.specDone).toHaveBeenCalledWith( + jasmine.objectContaining({ + failedExpectations: [] + }) + ); + }); + + it('works when there is no current runable', function() { + expect(env.pp({ some: 'thing' })).toEqual("Object({ some: 'thing' })"); + }); + }); + it('forbids duplicates when forbidDuplicateNames is true', function() { env.configure({ forbidDuplicateNames: true }); env.it('a spec'); diff --git a/src/core/Env.js b/src/core/Env.js index 2a95065e..c6e5d39b 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -821,6 +821,13 @@ getJasmineRequireObj().Env = function(j$) { } }; + this.pp = function(value) { + const pp = runner.currentRunable() + ? runableResources.makePrettyPrinter() + : j$.private.basicPrettyPrinter; + return pp(value); + }; + this.cleanup_ = function() { uninstallGlobalErrors(); }; diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index a3b97768..0ad6f61c 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -13,7 +13,7 @@ getJasmineRequireObj().MatchersUtil = function(j$) { this.customTesters_ = options.customTesters || []; /** * Formats a value for use in matcher failure messages and similar contexts, - * taking into account the current set of custom value formatters. + * taking into account the current set of custom object formatters. * @function * @name MatchersUtil#pp * @since 3.6.0 diff --git a/src/core/requireInterface.js b/src/core/requireInterface.js index bcdb7fe0..a8833bb1 100644 --- a/src/core/requireInterface.js +++ b/src/core/requireInterface.js @@ -498,6 +498,21 @@ getJasmineRequireObj().interface = function(jasmine, env) { return env.setDefaultSpyStrategy(defaultStrategyFn); }; + /** + * Formats a value for display, taking into account the current set of + * custom object formatters. + * + * @name jasmine.pp + * @function + * @since 6.0.0 + * @param {*} value The value to pretty-print + * @return {string} The pretty-printed value + * @see {MatchersUtil#pp} + */ + jasmine.pp = function(value) { + return env.pp(value); + }; + /** * {@link AsymmetricEqualityTester|Asymmetric equality testers} allow for * non-exact matching in matchers that use Jasmine's deep value equality