diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 83f53eb1..4cd407d4 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -113,6 +113,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.Falsy = jRequire.Falsy(j$); j$.Empty = jRequire.Empty(j$); j$.NotEmpty = jRequire.NotEmpty(j$); + j$.Exactly = jRequire.Exactly(j$); j$.matchers = jRequire.requireMatchers(jRequire, j$); j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$); @@ -453,6 +454,18 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return new j$.Empty(); }; + /** + * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} + * that passes if the actual value is the same as the sample as determined + * by the `===` operator. + * @name jasmine.exactly + * @function + * @param {Object} sample - The value to compare the actual to. + */ + j$.exactly = function(sample) { + return new j$.Exactly(sample); + }; + /** * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value being compared is not empty. @@ -2800,6 +2813,24 @@ getJasmineRequireObj().Empty = function(j$) { return Empty; }; +getJasmineRequireObj().Exactly = function(j$) { + class Exactly { + constructor(expected) { + this.expected_ = expected; + } + + asymmetricMatch(actual) { + return actual === this.expected_; + } + + jasmineToString(pp) { + return ``; + } + } + + return Exactly; +}; + getJasmineRequireObj().Falsy = function(j$) { function Falsy() {} diff --git a/spec/core/SuiteSpec.js b/spec/core/SuiteSpec.js index 6813082a..87b0fcfd 100644 --- a/spec/core/SuiteSpec.js +++ b/spec/core/SuiteSpec.js @@ -71,20 +71,9 @@ describe('Suite', function() { suite.beforeAll(outerBefore); suite.beforeAll(innerBefore); - function sameInstance(expected) { - return { - asymmetricMatch: function(actual) { - return actual === expected; - }, - jasmineToString: function() { - return ``; - } - }; - } - expect(suite.beforeAllFns).toEqual([ - { fn: outerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) }, - { fn: innerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) } + { fn: outerBefore.fn, type: 'beforeAll', suite: jasmine.exactly(suite) }, + { fn: innerBefore.fn, type: 'beforeAll', suite: jasmine.exactly(suite) } ]); }); diff --git a/spec/core/asymmetric_equality/ExactlySpec.js b/spec/core/asymmetric_equality/ExactlySpec.js new file mode 100644 index 00000000..371370b6 --- /dev/null +++ b/spec/core/asymmetric_equality/ExactlySpec.js @@ -0,0 +1,30 @@ +describe('Exactly', function() { + it('passes for primitives that are ===', function() { + const exactly = new jasmineUnderTest.Exactly(17); + expect(exactly.asymmetricMatch(17)).toBeTrue(); + }); + + it('fails for primitives that are not ===', function() { + const exactly = new jasmineUnderTest.Exactly(42); + expect(exactly.asymmetricMatch('42')).toBeFalse(); + }); + + it('passes for the same object instance', function() { + const obj = {}; + const exactly = new jasmineUnderTest.Exactly(obj); + expect(exactly.asymmetricMatch(obj)).toBeTrue(); + }); + + it('fails for different object instances, even if they are deep value equal', function() { + const exactly = new jasmineUnderTest.Exactly({}); + expect(exactly.asymmetricMatch({})).toBeFalse(); + }); + + it('describes itself for use in diffs and pretty printing', function() { + const exactly = new jasmineUnderTest.Exactly({ foo: ['bar'] }); + const pp = jasmineUnderTest.basicPrettyPrinter_; + expect(exactly.jasmineToString(pp)).toEqual( + "" + ); + }); +}); diff --git a/src/core/asymmetric_equality/Exactly.js b/src/core/asymmetric_equality/Exactly.js new file mode 100644 index 00000000..e748f772 --- /dev/null +++ b/src/core/asymmetric_equality/Exactly.js @@ -0,0 +1,17 @@ +getJasmineRequireObj().Exactly = function(j$) { + class Exactly { + constructor(expected) { + this.expected_ = expected; + } + + asymmetricMatch(actual) { + return actual === this.expected_; + } + + jasmineToString(pp) { + return ``; + } + } + + return Exactly; +}; diff --git a/src/core/base.js b/src/core/base.js index 2e953541..e9b05bb1 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -283,6 +283,18 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { return new j$.Empty(); }; + /** + * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} + * that passes if the actual value is the same as the sample as determined + * by the `===` operator. + * @name jasmine.exactly + * @function + * @param {Object} sample - The value to compare the actual to. + */ + j$.exactly = function(sample) { + return new j$.Exactly(sample); + }; + /** * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value being compared is not empty. diff --git a/src/core/requireCore.js b/src/core/requireCore.js index e8e17994..f0567dbc 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -91,6 +91,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.Falsy = jRequire.Falsy(j$); j$.Empty = jRequire.Empty(j$); j$.NotEmpty = jRequire.NotEmpty(j$); + j$.Exactly = jRequire.Exactly(j$); j$.matchers = jRequire.requireMatchers(jRequire, j$); j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);