Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4be08b657 | ||
|
|
50ef882a1a | ||
|
|
c1cd5c6291 | ||
|
|
63ed2b3948 | ||
|
|
0183acc682 | ||
|
|
e15819c0dd | ||
|
|
f694194b2b | ||
|
|
94c00886a6 | ||
|
|
f5915d7963 | ||
|
|
15587f3ce3 | ||
|
|
3ecddc2555 | ||
|
|
6a7c0e6368 | ||
|
|
84daa0f5dc | ||
|
|
c6b3e947e9 |
@@ -4,6 +4,10 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
executors:
|
executors:
|
||||||
|
node24:
|
||||||
|
docker:
|
||||||
|
- image: cimg/node:24.0.0
|
||||||
|
working_directory: ~/workspace
|
||||||
node22:
|
node22:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/node:22.0.0
|
- image: cimg/node:22.0.0
|
||||||
@@ -100,6 +104,9 @@ workflows:
|
|||||||
|
|
||||||
push:
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
|
- build:
|
||||||
|
executor: node24
|
||||||
|
name: build_node_24
|
||||||
- build:
|
- build:
|
||||||
executor: node22
|
executor: node22
|
||||||
name: build_node_22
|
name: build_node_22
|
||||||
@@ -125,10 +132,10 @@ workflows:
|
|||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_18
|
||||||
- test_parallel:
|
- test_parallel:
|
||||||
executor: node18
|
executor: node24
|
||||||
name: test_parallel_node_18
|
name: test_parallel_node_24
|
||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_24
|
||||||
- test_parallel:
|
- test_parallel:
|
||||||
executor: node22
|
executor: node22
|
||||||
name: test_parallel_node_22
|
name: test_parallel_node_22
|
||||||
@@ -139,6 +146,11 @@ workflows:
|
|||||||
name: test_parallel_node_20
|
name: test_parallel_node_20
|
||||||
requires:
|
requires:
|
||||||
- build_node_20
|
- build_node_20
|
||||||
|
- test_parallel:
|
||||||
|
executor: node18
|
||||||
|
name: test_parallel_node_18
|
||||||
|
requires:
|
||||||
|
- build_node_18
|
||||||
- test_browsers:
|
- test_browsers:
|
||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_18
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Microsoft Edge) as well as Node.
|
|||||||
|
|
||||||
| Environment | Supported versions |
|
| Environment | Supported versions |
|
||||||
|-------------------|----------------------------|
|
|-------------------|----------------------------|
|
||||||
| Node | 18, 20, 22 |
|
| Node | 18, 20, 22, 24 |
|
||||||
| Safari | 15*, 16*, 17* |
|
| Safari | 15*, 16*, 17* |
|
||||||
| Chrome | Evergreen |
|
| Chrome | Evergreen |
|
||||||
| Firefox | Evergreen, 102*, 115*, 128 |
|
| Firefox | Evergreen, 102*, 115*, 128 |
|
||||||
|
|||||||
@@ -2803,7 +2803,7 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
|||||||
|
|
||||||
this.track = function(context) {
|
this.track = function(context) {
|
||||||
if (opts.cloneArgs) {
|
if (opts.cloneArgs) {
|
||||||
context.args = j$.util.cloneArgs(context.args);
|
context.args = opts.argsCloner(context.args);
|
||||||
}
|
}
|
||||||
calls.push(context);
|
calls.push(context);
|
||||||
};
|
};
|
||||||
@@ -2911,13 +2911,15 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this spy to do a shallow clone of arguments passed to each invocation.
|
* Set this spy to do a clone of arguments passed to each invocation.
|
||||||
* @name Spy#calls#saveArgumentsByValue
|
* @name Spy#calls#saveArgumentsByValue
|
||||||
* @since 2.5.0
|
* @since 2.5.0
|
||||||
|
* @param {Function} [argsCloner] A function to use to clone the arguments. Defaults to a shallow cloning function.
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.saveArgumentsByValue = function() {
|
this.saveArgumentsByValue = function(argsCloner = j$.util.cloneArgs) {
|
||||||
opts.cloneArgs = true;
|
opts.cloneArgs = true;
|
||||||
|
opts.argsCloner = argsCloner;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.unverifiedCount = function() {
|
this.unverifiedCount = function() {
|
||||||
@@ -3125,6 +3127,10 @@ getJasmineRequireObj().Clock = function() {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.uninstall = function() {
|
this.uninstall = function() {
|
||||||
|
// Ensure auto ticking loop is aborted when clock is uninstalled
|
||||||
|
if (tickMode.mode === 'auto') {
|
||||||
|
tickMode = { mode: 'manual', counter: tickMode.counter + 1 };
|
||||||
|
}
|
||||||
delayedFunctionScheduler = null;
|
delayedFunctionScheduler = null;
|
||||||
mockDate.uninstall();
|
mockDate.uninstall();
|
||||||
replace(global, realTimingFunctions);
|
replace(global, realTimingFunctions);
|
||||||
@@ -3278,6 +3284,12 @@ callbacks to execute _before_ running the next one.
|
|||||||
//
|
//
|
||||||
// @return {!Promise<undefined>}
|
// @return {!Promise<undefined>}
|
||||||
async function newMacrotask() {
|
async function newMacrotask() {
|
||||||
|
if (NODE_JS) {
|
||||||
|
// setImmediate is generally faster than setTimeout in Node
|
||||||
|
// https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick#setimmediate-vs-settimeout
|
||||||
|
return new Promise(resolve => void setImmediate(resolve));
|
||||||
|
}
|
||||||
|
|
||||||
// MessageChannel ensures that setTimeout is not throttled to 4ms.
|
// MessageChannel ensures that setTimeout is not throttled to 4ms.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
|
// https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
|
||||||
// https://stackblitz.com/edit/stackblitz-starters-qtlpcc
|
// https://stackblitz.com/edit/stackblitz-starters-qtlpcc
|
||||||
@@ -4871,7 +4883,10 @@ getJasmineRequireObj().DiffBuilder = function(j$) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (useCustom) {
|
if (useCustom) {
|
||||||
messages.push(wrapPrettyPrinted(actualCustom, expectedCustom, path));
|
const prettyActual = actualCustom || this.prettyPrinter_(actual);
|
||||||
|
const prettyExpected =
|
||||||
|
expectedCustom || this.prettyPrinter_(expected);
|
||||||
|
messages.push(wrapPrettyPrinted(prettyActual, prettyExpected, path));
|
||||||
return false; // don't recurse further
|
return false; // don't recurse further
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7748,7 +7763,11 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
|||||||
} else if (value instanceof RegExp) {
|
} else if (value instanceof RegExp) {
|
||||||
this.emitScalar(value.toString());
|
this.emitScalar(value.toString());
|
||||||
} else if (typeof value === 'function') {
|
} else if (typeof value === 'function') {
|
||||||
this.emitScalar('Function');
|
if (value.name) {
|
||||||
|
this.emitScalar(`Function '${value.name}'`);
|
||||||
|
} else {
|
||||||
|
this.emitScalar('Function');
|
||||||
|
}
|
||||||
} else if (j$.isDomNode(value)) {
|
} else if (j$.isDomNode(value)) {
|
||||||
if (value.tagName) {
|
if (value.tagName) {
|
||||||
this.emitDomElement(value);
|
this.emitDomElement(value);
|
||||||
@@ -9664,7 +9683,7 @@ getJasmineRequireObj().Spy = function(j$) {
|
|||||||
"Spy '" +
|
"Spy '" +
|
||||||
strategyArgs.name +
|
strategyArgs.name +
|
||||||
"' received a call with arguments " +
|
"' received a call with arguments " +
|
||||||
j$.basicPrettyPrinter_(Array.prototype.slice.call(args)) +
|
matchersUtil.pp(Array.prototype.slice.call(args)) +
|
||||||
' but all configured strategies specify other arguments.'
|
' but all configured strategies specify other arguments.'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -11391,5 +11410,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().version = function() {
|
getJasmineRequireObj().version = function() {
|
||||||
return '5.7.0';
|
return '5.8.0';
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jasmine-core",
|
"name": "jasmine-core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "5.7.0",
|
"version": "5.8.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jasmine/jasmine.git"
|
"url": "https://github.com/jasmine/jasmine.git"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
to automatically tick the clock asynchronously
|
to automatically tick the clock asynchronously
|
||||||
* Merges #2042 from @atscott and @stephenfarrar
|
* Merges #2042 from @atscott and @stephenfarrar
|
||||||
* Fixes #1725
|
* Fixes #1725
|
||||||
* Fixes #1932
|
|
||||||
|
|
||||||
* Expose [spec path](https://jasmine.github.io/api/5.7/Spec.html#getPath) as an
|
* Expose [spec path](https://jasmine.github.io/api/5.7/Spec.html#getPath) as an
|
||||||
array of names in addition to the existing concatenated name
|
array of names in addition to the existing concatenated name
|
||||||
@@ -54,10 +53,9 @@ This version has been tested in the following environments.
|
|||||||
|
|
||||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||||
version available at release time.<br>
|
version available at release time.<br>
|
||||||
\** Environments that are past end of life are supported on a best-effort basis.
|
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||||
They may be dropped in a future minor release of Jasmine if continued support
|
if it becomes impractical, and bugs affecting only these versions may not be
|
||||||
becomes impractical.
|
treated as release blockers.
|
||||||
|
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|||||||
28
release_notes/5.7.1.md
Normal file
28
release_notes/5.7.1.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Jasmine Core 5.7.1 Release Notes
|
||||||
|
|
||||||
|
## Bug fixes
|
||||||
|
|
||||||
|
* Ensure that uninstalling the clock also stops auto tick
|
||||||
|
* Merges #2057 from @atscott
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
This version has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|-------------------------|
|
||||||
|
| Node | 18**, 20, 22 |
|
||||||
|
| Safari | 15**, 16**, 17** |
|
||||||
|
| Chrome | 136* |
|
||||||
|
| Firefox | 102**, 115**, 128, 138* |
|
||||||
|
| Edge | 135* |
|
||||||
|
|
||||||
|
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||||
|
version available at release time.<br>
|
||||||
|
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||||
|
if it becomes impractical, and bugs affecting only these versions may not be
|
||||||
|
treated as release blockers.
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
44
release_notes/5.8.0.md
Normal file
44
release_notes/5.8.0.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Jasmine Core 5.8.0 Release Notes
|
||||||
|
|
||||||
|
## New Features
|
||||||
|
|
||||||
|
* Allow passing a function to `saveArgumentsByValue` to customize how arguments
|
||||||
|
are saved
|
||||||
|
* Merges [#2062](https://github.com/jasmine/jasmine/pull/2062) from @evanwaslh
|
||||||
|
* Fixes [#1886](https://github.com/jasmine/jasmine/issues/1886)
|
||||||
|
* Use custom object formatters in spy strategy mismatch errors
|
||||||
|
* Include function names in pretty printer output
|
||||||
|
* Improve performance of autoTick in Node
|
||||||
|
* Merges [#2058](https://github.com/jasmine/jasmine/pull/2058) from @atscott
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
* Fix diff building when only one side has a custom object formatter
|
||||||
|
* Fixes [#2061](https://github.com/jasmine/jasmine/issues/2061)
|
||||||
|
|
||||||
|
## Documentation improvements
|
||||||
|
|
||||||
|
* Added Node 24 to supported environments
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
This version has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|-------------------------|
|
||||||
|
| Node | 18**, 20, 22, 24 |
|
||||||
|
| Safari | 15**, 16**, 17** |
|
||||||
|
| Chrome | 137* |
|
||||||
|
| Firefox | 102**, 115**, 128, 139* |
|
||||||
|
| Edge | 137* |
|
||||||
|
|
||||||
|
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||||
|
version available at release time.<br>
|
||||||
|
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||||
|
if it becomes impractical, and bugs affecting only these versions may not be
|
||||||
|
treated as release blockers.
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
@@ -134,6 +134,42 @@ describe('CallTracker', function() {
|
|||||||
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('allows object arguments to be deep cloned', function() {
|
||||||
|
const callTracker = new jasmineUnderTest.CallTracker();
|
||||||
|
callTracker.saveArgumentsByValue(args => JSON.parse(JSON.stringify(args)));
|
||||||
|
|
||||||
|
const objectArg = { foo: { bar: { baz: ['qux'] } } },
|
||||||
|
arrayArg = ['foo', 'bar'];
|
||||||
|
|
||||||
|
callTracker.track({
|
||||||
|
object: {},
|
||||||
|
args: [objectArg, arrayArg, false, undefined, null, NaN, '', 0, 1.0]
|
||||||
|
});
|
||||||
|
|
||||||
|
objectArg.foo.bar.baz.push('quux');
|
||||||
|
|
||||||
|
expect(callTracker.mostRecent().args[0]).not.toBe(objectArg);
|
||||||
|
expect(callTracker.mostRecent().args[0]).not.toEqual(objectArg);
|
||||||
|
expect(callTracker.mostRecent().args[0]).toEqual({
|
||||||
|
foo: { bar: { baz: ['qux'] } }
|
||||||
|
});
|
||||||
|
expect(callTracker.mostRecent().args[1]).not.toBe(arrayArg);
|
||||||
|
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can take any function to transform arguments when saving by value', function() {
|
||||||
|
const callTracker = new jasmineUnderTest.CallTracker();
|
||||||
|
callTracker.saveArgumentsByValue(JSON.stringify);
|
||||||
|
|
||||||
|
const objectArg = { foo: { bar: { baz: ['qux'] } } },
|
||||||
|
arrayArg = ['foo', 'bar'],
|
||||||
|
args = [objectArg, arrayArg, false, undefined, null, NaN, '', 0, 1.0];
|
||||||
|
|
||||||
|
callTracker.track({ object: {}, args });
|
||||||
|
|
||||||
|
expect(callTracker.mostRecent().args).toEqual(JSON.stringify(args));
|
||||||
|
});
|
||||||
|
|
||||||
it('saves primitive arguments by value', function() {
|
it('saves primitive arguments by value', function() {
|
||||||
const callTracker = new jasmineUnderTest.CallTracker(),
|
const callTracker = new jasmineUnderTest.CallTracker(),
|
||||||
args = [undefined, null, false, '', /\s/, 0, 1.2, NaN];
|
args = [undefined, null, false, '', /\s/, 0, 1.2, NaN];
|
||||||
|
|||||||
@@ -699,22 +699,39 @@ describe('Clock (acceptance)', function() {
|
|||||||
tick: function() {},
|
tick: function() {},
|
||||||
uninstall: function() {}
|
uninstall: function() {}
|
||||||
};
|
};
|
||||||
|
// window setTimeout to window to make firefox happy
|
||||||
|
const _setTimeout =
|
||||||
|
typeof window !== 'undefined' ? setTimeout.bind(window) : setTimeout;
|
||||||
|
// passing a fake global allows us to preserve the real timing functions for use in tests
|
||||||
|
const _global = { setTimeout: _setTimeout, setInterval: setInterval };
|
||||||
clock = new jasmineUnderTest.Clock(
|
clock = new jasmineUnderTest.Clock(
|
||||||
// We use the real window for global or firefox is displeased when we try to call a real setTimeout on an object "that doesn't implement window".
|
_global,
|
||||||
typeof window !== 'undefined' ? window : { setTimeout: setTimeout },
|
|
||||||
function() {
|
function() {
|
||||||
return delayedFunctionScheduler;
|
return delayedFunctionScheduler;
|
||||||
},
|
},
|
||||||
mockDate
|
mockDate
|
||||||
);
|
);
|
||||||
clock.install();
|
clock.install().autoTick();
|
||||||
clock.autoTick();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
clock.uninstall();
|
clock.uninstall();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('flushes microtask queue between macrotasks', async () => {
|
||||||
|
const log = [];
|
||||||
|
await new Promise(r => clock.setTimeout(r, 10)).then(() => {
|
||||||
|
log.push(1);
|
||||||
|
Promise.resolve().then(() => log.push(2));
|
||||||
|
Promise.resolve().then(() => log.push(3));
|
||||||
|
});
|
||||||
|
await new Promise(r => clock.setTimeout(r, 10)).then(() => {
|
||||||
|
log.push(4);
|
||||||
|
Promise.resolve().then(() => log.push(5));
|
||||||
|
});
|
||||||
|
expect(log).toEqual([1, 2, 3, 4, 5]);
|
||||||
|
});
|
||||||
|
|
||||||
it('can run setTimeouts/setIntervals asynchronously', function() {
|
it('can run setTimeouts/setIntervals asynchronously', function() {
|
||||||
const recurring = jasmine.createSpy('recurring'),
|
const recurring = jasmine.createSpy('recurring'),
|
||||||
fn1 = jasmine.createSpy('fn1'),
|
fn1 = jasmine.createSpy('fn1'),
|
||||||
@@ -776,6 +793,26 @@ describe('Clock (acceptance)', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('aborts auto ticking when uninstalled, even if installed again synchonrously', async () => {
|
||||||
|
clock.uninstall();
|
||||||
|
clock.install();
|
||||||
|
|
||||||
|
let resolved = false;
|
||||||
|
const promise = new Promise(resolve => {
|
||||||
|
clock.setTimeout(resolve, 1);
|
||||||
|
}).then(() => {
|
||||||
|
resolved = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// wait some real time and verify that the clock did not flush the timer above automatically
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2));
|
||||||
|
expect(resolved).toBe(false);
|
||||||
|
|
||||||
|
// enabling auto tick again will flush the timer
|
||||||
|
clock.autoTick();
|
||||||
|
await expectAsync(promise).toBeResolved();
|
||||||
|
});
|
||||||
|
|
||||||
it('speeds up the execution of the timers in all browsers', async () => {
|
it('speeds up the execution of the timers in all browsers', async () => {
|
||||||
const startTimeMs = performance.now() / 1000;
|
const startTimeMs = performance.now() / 1000;
|
||||||
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ describe('PrettyPrinter', function() {
|
|||||||
"Object({ foo: 'bar', baz: 3, nullValue: null, undefinedValue: undefined })"
|
"Object({ foo: 'bar', baz: 3, nullValue: null, undefinedValue: undefined })"
|
||||||
);
|
);
|
||||||
expect(pp({ foo: function() {}, bar: [1, 2, 3] })).toEqual(
|
expect(pp({ foo: function() {}, bar: [1, 2, 3] })).toEqual(
|
||||||
'Object({ foo: Function, bar: [ 1, 2, 3 ] })'
|
"Object({ foo: Function 'foo', bar: [ 1, 2, 3 ] })"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ describe('PrettyPrinter', function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
expect(pp(objFromOtherContext)).toEqual(
|
expect(pp(objFromOtherContext)).toEqual(
|
||||||
"Object({ foo: 'bar', toString: Function })"
|
"Object({ foo: 'bar', toString: Function 'toString' })"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -477,6 +477,17 @@ describe('PrettyPrinter', function() {
|
|||||||
expect(pp(a)).toEqual('<anonymous>({ })');
|
expect(pp(a)).toEqual('<anonymous>({ })');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('stringifies functions with names', function() {
|
||||||
|
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||||
|
expect(pp(foo)).toEqual("Function 'foo'");
|
||||||
|
function foo() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stringifies functions without names', function() {
|
||||||
|
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||||
|
expect(pp(function() {})).toEqual('Function');
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle objects with null prototype', function() {
|
it('should handle objects with null prototype', function() {
|
||||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||||
const obj = Object.create(null);
|
const obj = Object.create(null);
|
||||||
|
|||||||
@@ -3855,6 +3855,35 @@ describe('Env integration', function() {
|
|||||||
expect(failedExpectations).toEqual([]);
|
expect(failedExpectations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses custom object formatters in spy strategy argument mismatch errors', async function() {
|
||||||
|
env.it('a spec', function() {
|
||||||
|
env.addCustomObjectFormatter(function(value) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return 'custom:' + value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const spy = env
|
||||||
|
.createSpy('foo')
|
||||||
|
.withArgs('x')
|
||||||
|
.and.returnValue('');
|
||||||
|
spy('y');
|
||||||
|
});
|
||||||
|
|
||||||
|
let failedExpectations;
|
||||||
|
env.addReporter({
|
||||||
|
specDone: r => (failedExpectations = r.failedExpectations)
|
||||||
|
});
|
||||||
|
|
||||||
|
await env.execute();
|
||||||
|
expect(failedExpectations).toEqual([
|
||||||
|
jasmine.objectContaining({
|
||||||
|
message: jasmine.stringContaining(
|
||||||
|
'received a call with arguments [ custom:y ]'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
describe('#spyOnGlobalErrorsAsync', function() {
|
describe('#spyOnGlobalErrorsAsync', function() {
|
||||||
const leftInstalledMessage =
|
const leftInstalledMessage =
|
||||||
'Global error spy was not uninstalled. ' +
|
'Global error spy was not uninstalled. ' +
|
||||||
|
|||||||
@@ -161,6 +161,63 @@ describe('DiffBuilder', function() {
|
|||||||
expect(diffBuilder.getMessage()).toEqual(expectedMsg);
|
expect(diffBuilder.getMessage()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles cases where only the expected has a custom object formatter', function() {
|
||||||
|
const formatter = function(x) {
|
||||||
|
if (typeof x === 'number') {
|
||||||
|
return '[number:' + x + ']';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]);
|
||||||
|
const diffBuilder = new jasmineUnderTest.DiffBuilder({
|
||||||
|
prettyPrinter: prettyPrinter
|
||||||
|
});
|
||||||
|
|
||||||
|
diffBuilder.setRoots('five', 4);
|
||||||
|
diffBuilder.recordMismatch();
|
||||||
|
|
||||||
|
expect(diffBuilder.getMessage()).toEqual(
|
||||||
|
"Expected 'five' to equal [number:4]."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles cases where only the actual has a custom object formatter', function() {
|
||||||
|
const formatter = function(x) {
|
||||||
|
if (typeof x === 'number') {
|
||||||
|
return '[number:' + x + ']';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]);
|
||||||
|
const diffBuilder = new jasmineUnderTest.DiffBuilder({
|
||||||
|
prettyPrinter: prettyPrinter
|
||||||
|
});
|
||||||
|
|
||||||
|
diffBuilder.setRoots(5, 'four');
|
||||||
|
diffBuilder.recordMismatch();
|
||||||
|
|
||||||
|
expect(diffBuilder.getMessage()).toEqual(
|
||||||
|
"Expected [number:5] to equal 'four'."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles complex cases where only one side has a custom object formatter', function() {
|
||||||
|
const formatter = function(x) {
|
||||||
|
if (typeof x === 'number') {
|
||||||
|
return '[number:' + x + ']';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]);
|
||||||
|
const diffBuilder = new jasmineUnderTest.DiffBuilder({
|
||||||
|
prettyPrinter: prettyPrinter
|
||||||
|
});
|
||||||
|
|
||||||
|
diffBuilder.setRoots(5, { foo: 'bar', fnord: { graults: ['wombat'] } });
|
||||||
|
diffBuilder.recordMismatch();
|
||||||
|
|
||||||
|
expect(diffBuilder.getMessage()).toEqual(
|
||||||
|
"Expected [number:5] to equal Object({ foo: 'bar', fnord: Object({ graults: [ 'wombat' ] }) })."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('builds diffs involving asymmetric equality testers that implement valuesForDiff_ at the root', function() {
|
it('builds diffs involving asymmetric equality testers that implement valuesForDiff_ at the root', function() {
|
||||||
const prettyPrinter = jasmineUnderTest.makePrettyPrinter([]),
|
const prettyPrinter = jasmineUnderTest.makePrettyPrinter([]),
|
||||||
diffBuilder = new jasmineUnderTest.DiffBuilder({
|
diffBuilder = new jasmineUnderTest.DiffBuilder({
|
||||||
|
|||||||
@@ -458,9 +458,9 @@ describe('toEqual', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('reports mismatches between Functions', function() {
|
it('reports mismatches between Functions', function() {
|
||||||
const actual = { x: function() {} },
|
const actual = { x: function() {} };
|
||||||
expected = { x: function() {} },
|
const expected = { x: function() {} };
|
||||||
message = 'Expected $.x = Function to equal Function.';
|
const message = "Expected $.x = Function 'x' to equal Function 'x'.";
|
||||||
|
|
||||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
|||||||
|
|
||||||
this.track = function(context) {
|
this.track = function(context) {
|
||||||
if (opts.cloneArgs) {
|
if (opts.cloneArgs) {
|
||||||
context.args = j$.util.cloneArgs(context.args);
|
context.args = opts.argsCloner(context.args);
|
||||||
}
|
}
|
||||||
calls.push(context);
|
calls.push(context);
|
||||||
};
|
};
|
||||||
@@ -117,13 +117,15 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this spy to do a shallow clone of arguments passed to each invocation.
|
* Set this spy to do a clone of arguments passed to each invocation.
|
||||||
* @name Spy#calls#saveArgumentsByValue
|
* @name Spy#calls#saveArgumentsByValue
|
||||||
* @since 2.5.0
|
* @since 2.5.0
|
||||||
|
* @param {Function} [argsCloner] A function to use to clone the arguments. Defaults to a shallow cloning function.
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.saveArgumentsByValue = function() {
|
this.saveArgumentsByValue = function(argsCloner = j$.util.cloneArgs) {
|
||||||
opts.cloneArgs = true;
|
opts.cloneArgs = true;
|
||||||
|
opts.argsCloner = argsCloner;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.unverifiedCount = function() {
|
this.unverifiedCount = function() {
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ getJasmineRequireObj().Clock = function() {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
this.uninstall = function() {
|
this.uninstall = function() {
|
||||||
|
// Ensure auto ticking loop is aborted when clock is uninstalled
|
||||||
|
if (tickMode.mode === 'auto') {
|
||||||
|
tickMode = { mode: 'manual', counter: tickMode.counter + 1 };
|
||||||
|
}
|
||||||
delayedFunctionScheduler = null;
|
delayedFunctionScheduler = null;
|
||||||
mockDate.uninstall();
|
mockDate.uninstall();
|
||||||
replace(global, realTimingFunctions);
|
replace(global, realTimingFunctions);
|
||||||
@@ -222,6 +226,12 @@ callbacks to execute _before_ running the next one.
|
|||||||
//
|
//
|
||||||
// @return {!Promise<undefined>}
|
// @return {!Promise<undefined>}
|
||||||
async function newMacrotask() {
|
async function newMacrotask() {
|
||||||
|
if (NODE_JS) {
|
||||||
|
// setImmediate is generally faster than setTimeout in Node
|
||||||
|
// https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick#setimmediate-vs-settimeout
|
||||||
|
return new Promise(resolve => void setImmediate(resolve));
|
||||||
|
}
|
||||||
|
|
||||||
// MessageChannel ensures that setTimeout is not throttled to 4ms.
|
// MessageChannel ensures that setTimeout is not throttled to 4ms.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
|
// https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
|
||||||
// https://stackblitz.com/edit/stackblitz-starters-qtlpcc
|
// https://stackblitz.com/edit/stackblitz-starters-qtlpcc
|
||||||
|
|||||||
@@ -35,7 +35,11 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
|||||||
} else if (value instanceof RegExp) {
|
} else if (value instanceof RegExp) {
|
||||||
this.emitScalar(value.toString());
|
this.emitScalar(value.toString());
|
||||||
} else if (typeof value === 'function') {
|
} else if (typeof value === 'function') {
|
||||||
this.emitScalar('Function');
|
if (value.name) {
|
||||||
|
this.emitScalar(`Function '${value.name}'`);
|
||||||
|
} else {
|
||||||
|
this.emitScalar('Function');
|
||||||
|
}
|
||||||
} else if (j$.isDomNode(value)) {
|
} else if (j$.isDomNode(value)) {
|
||||||
if (value.tagName) {
|
if (value.tagName) {
|
||||||
this.emitDomElement(value);
|
this.emitDomElement(value);
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ getJasmineRequireObj().Spy = function(j$) {
|
|||||||
"Spy '" +
|
"Spy '" +
|
||||||
strategyArgs.name +
|
strategyArgs.name +
|
||||||
"' received a call with arguments " +
|
"' received a call with arguments " +
|
||||||
j$.basicPrettyPrinter_(Array.prototype.slice.call(args)) +
|
matchersUtil.pp(Array.prototype.slice.call(args)) +
|
||||||
' but all configured strategies specify other arguments.'
|
' but all configured strategies specify other arguments.'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ getJasmineRequireObj().DiffBuilder = function(j$) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (useCustom) {
|
if (useCustom) {
|
||||||
messages.push(wrapPrettyPrinted(actualCustom, expectedCustom, path));
|
const prettyActual = actualCustom || this.prettyPrinter_(actual);
|
||||||
|
const prettyExpected =
|
||||||
|
expectedCustom || this.prettyPrinter_(expected);
|
||||||
|
messages.push(wrapPrettyPrinted(prettyActual, prettyExpected, path));
|
||||||
return false; // don't recurse further
|
return false; // don't recurse further
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user