Compare commits

...

21 Commits

Author SHA1 Message Date
Steve Gravrock
e5e0e6481d Bump version to 4.2.0 2022-06-09 18:18:45 -07:00
Steve Gravrock
bcf69b86b4 Removed duplicate Suite and Spec jsdocs 2022-06-03 12:22:58 -07:00
Steve Gravrock
a5f79fac81 Removed remaining jshint config comments 2022-06-02 18:22:23 -07:00
Steve Gravrock
18a00822c5 Built distribution 2022-06-02 11:37:10 -07:00
Steve Gravrock
4cc8437f79 Call buildExpectationResult directly from Suite and Spec
This removes quite a bit of indirection from result processing, at the
cost of making a few of the tests more awkward.
2022-06-01 10:18:23 -07:00
Steve Gravrock
8e58305b0a ExpectationResult.js -> buildExpectationResult.js 2022-06-01 09:26:21 -07:00
Steve Gravrock
bd368aceee Replaced var with const and let in expectation related code 2022-06-01 09:22:03 -07:00
Steve Gravrock
8f16021887 Replaced var with const and let in ExpectationResult 2022-06-01 09:02:43 -07:00
Steve Gravrock
bbb1b69b2e More reliably report errors that occur late in the suite/spec lifecycle
Previously, an error that occurred after Jasmine started to report the
suiteDone or specDone event for the current runable would not be reliably
reported. Now such an error is reported on the nearest ancestor suite whose
suiteDone event has not yet been reported.
2022-05-28 18:10:55 -07:00
Steve Gravrock
9ea8a2096f Additional integration tests for existing async error handling 2022-05-28 18:01:19 -07:00
Steve Gravrock
66340e2b19 Updated browserslist to match 4.0 envs 2022-05-28 18:00:45 -07:00
Steve Gravrock
fe29dfa89c Update release process instructions
* Need to tag the release manually since the Ruby tooling for that was
  removed
* Windows CI works again, so no need to manually test on Windows
2022-05-21 09:43:43 -07:00
Steve Gravrock
41f7fabe2f Renamed jasmine.exactly to jasmine.is, for similarity with toBe 2022-05-21 08:30:53 -07:00
Steve Gravrock
856a040a2d Fixed flaky spec 2022-05-19 16:39:48 -07:00
Steve Gravrock
f7eaa5ec29 Fixed failing CI builds for Node 12 and 14
See https://github.com/npm/cli/issues/4896
2022-05-16 19:53:20 -07:00
Steve Gravrock
0c87d47318 Added a jasmine.exactly asymmetric equality tester 2022-05-14 17:01:38 -07:00
Steve Gravrock
c24b2f5a73 Converted some integration specs to async/await 2022-05-14 12:05:53 -07:00
Steve Gravrock
774c83a36e Don't report a deprecation when a runnable uses two forms of async
This was made into an error in 4.0, so the deprecation is redundant
(and broken).
2022-05-14 11:21:40 -07:00
Steve Gravrock
751cf6ab5b Converted DiffBuilder, ObjectPath, MismatchTree, and SinglePrettyPrintRun to ES6 classes 2022-05-14 11:15:08 -07:00
Steve Gravrock
2fd76c954c Replaced var with let and const in PrettyPrinter, DiffBuilder, and friends 2022-05-14 09:42:07 -07:00
Steve Gravrock
bb4d18f959 Include property getter values in pretty-printed objects
We already call getters when comparing objects for equality and generating
diffs, so it should be safe to do it here too.

See #1966.
2022-05-12 17:14:13 -07:00
38 changed files with 2458 additions and 2053 deletions

View File

@@ -36,9 +36,10 @@ When ready to release - specs are all green and the stories are done:
### Commit and push core changes ### Commit and push core changes
1. Run the browser tests using `scripts/run-all-browsers`. 1. Run the browser tests using `scripts/run-all-browsers`.
1. Commit release notes and version changes (jasmine.js, package.json) 2. Commit release notes and version changes (jasmine.js, package.json)
1. Push 3. Push
1. Wait for Circle CI to go green 4. Tag the release and push the tag.
5. Wait for Circle CI to go green
### Build standalone distribution ### Build standalone distribution
@@ -47,7 +48,6 @@ When ready to release - specs are all green and the stories are done:
### Release the core NPM module ### Release the core NPM module
1. Run the tests on Windows. (CI only tests on Linux.)
1. `npm adduser` to save your credentials locally 1. `npm adduser` to save your credentials locally
1. `npm publish .` to publish what's in `package.json` 1. `npm publish .` to publish what's in `package.json`

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "jasmine-core", "name": "jasmine-core",
"license": "MIT", "license": "MIT",
"version": "4.1.1", "version": "4.2.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/jasmine/jasmine.git" "url": "https://github.com/jasmine/jasmine.git"
@@ -43,8 +43,8 @@
"grunt-contrib-concat": "^2.0.0", "grunt-contrib-concat": "^2.0.0",
"grunt-css-url-embed": "^1.11.1", "grunt-css-url-embed": "^1.11.1",
"grunt-sass": "^3.0.2", "grunt-sass": "^3.0.2",
"jasmine": "github:jasmine/jasmine-npm#main", "jasmine": "^4.1.0",
"jasmine-browser-runner": "github:jasmine/jasmine-browser#main", "jasmine-browser-runner": "^1.0.0",
"jsdom": "^19.0.0", "jsdom": "^19.0.0",
"load-grunt-tasks": "^5.1.0", "load-grunt-tasks": "^5.1.0",
"prettier": "1.17.1", "prettier": "1.17.1",
@@ -95,14 +95,15 @@
"error", "error",
"always" "always"
], ],
"space-before-blocks": "error" "space-before-blocks": "error",
"no-eval": "error"
} }
}, },
"browserslist": [ "browserslist": [
"Safari >= 13", "Safari >= 14",
"last 2 Chrome versions", "last 2 Chrome versions",
"last 2 Firefox versions", "last 2 Firefox versions",
"Firefox >= 68", "Firefox >= 91",
"last 2 Edge versions" "last 2 Edge versions"
] ]
} }

29
release_notes/4.2.0.md Normal file
View File

@@ -0,0 +1,29 @@
# Jasmine 4.2.0 Release Notes
## New Features
* Added a jasmine.is asymmetric equality tester
* Allows the use of === comparisons for specific fields of an object that
should otherwise be compared with the default deep value equality logic.
## Bug Fixes
* More reliably report errors that occur late in the suite/spec lifecycle
* Previously, an error that occurred after Jasmine started to report the
suiteDone or specDone event for the current runable would not be reliably
reported. Now such an error is reported on the nearest ancestor suite whose
suiteDone event has not yet been reported.
* Don't report a deprecation when a runnable uses two forms of async
* This was made into an error in 4.0, so the deprecation is redundant.
* Include property getter values in pretty-printed objects
## Documentation Updates
* Removed duplicate Suite and Spec jsdocs
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -323,16 +323,16 @@ describe('PrettyPrinter', function() {
); );
}); });
it('should indicate getters on objects as such', function() { it('should use the return value of getters', function() {
const pp = jasmineUnderTest.makePrettyPrinter(); const pp = jasmineUnderTest.makePrettyPrinter();
const sampleValue = { const sampleValue = {
id: 1, id: 1,
get calculatedValue() { get calculatedValue() {
throw new Error("don't call me!"); return 'the getter return value';
} }
}; };
expect(pp(sampleValue)).toEqual( expect(pp(sampleValue)).toEqual(
'Object({ id: 1, calculatedValue: <getter> })' "Object({ id: 1, calculatedValue: 'the getter return value' })"
); );
}); });

View File

@@ -632,7 +632,8 @@ describe('QueueRunner', function() {
}); });
it('issues a more specific error if the function is `async`', function() { it('issues a more specific error if the function is `async`', function() {
eval('var fn = async function(done){};'); // eslint-disable-next-line no-unused-vars
async function fn(done) {}
const onException = jasmine.createSpy('onException'), const onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({ queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [{ fn: fn }], queueableFns: [{ fn: fn }],

View File

@@ -334,7 +334,7 @@ describe('Spec', function() {
const spec = new jasmineUnderTest.Spec({ const spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') } queueableFn: { fn: jasmine.createSpy('spec body') }
}); });
spec.addExpectationResult(true); spec.addExpectationResult(true, {});
expect(spec.status()).toBe('passed'); expect(spec.status()).toBe('passed');
}); });
@@ -342,8 +342,8 @@ describe('Spec', function() {
const spec = new jasmineUnderTest.Spec({ const spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') } queueableFn: { fn: jasmine.createSpy('spec body') }
}); });
spec.addExpectationResult(true); spec.addExpectationResult(true, {});
spec.addExpectationResult(false); spec.addExpectationResult(false, {});
expect(spec.status()).toBe('failed'); expect(spec.status()).toBe('failed');
}); });
@@ -352,14 +352,11 @@ describe('Spec', function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') }, queueableFn: { fn: jasmine.createSpy('spec body') },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner, queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback resultCallback: resultCallback
}); });
spec.addExpectationResult(true, 'expectation1'); spec.addExpectationResult(true, { message: 'expectation1' });
spec.addExpectationResult(false, 'expectation2'); spec.addExpectationResult(false, { message: 'expectation2' });
spec.execute(); spec.execute();
@@ -367,10 +364,10 @@ describe('Spec', function() {
fns[fns.length - 1].fn(); fns[fns.length - 1].fn();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual([ expect(resultCallback.calls.first().args[0].passedExpectations).toEqual([
'expectation1' jasmine.objectContaining({ message: 'expectation1' })
]); ]);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([ expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([
'expectation2' jasmine.objectContaining({ message: 'expectation2' })
]); ]);
}); });
@@ -379,17 +376,14 @@ describe('Spec', function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }, queueableFn: { fn: function() {} },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner, queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback, resultCallback: resultCallback,
throwOnExpectationFailure: true throwOnExpectationFailure: true
}); });
spec.addExpectationResult(true, 'passed'); spec.addExpectationResult(true, { message: 'passed' });
expect(function() { expect(function() {
spec.addExpectationResult(false, 'failed'); spec.addExpectationResult(false, { message: 'failed' });
}).toThrowError(jasmineUnderTest.errors.ExpectationFailed); }).toThrowError(jasmineUnderTest.errors.ExpectationFailed);
spec.execute(); spec.execute();
@@ -397,20 +391,104 @@ describe('Spec', function() {
const fns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns; const fns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
fns[fns.length - 1].fn(); fns[fns.length - 1].fn();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual([ expect(resultCallback.calls.first().args[0].passedExpectations).toEqual([
'passed' jasmine.objectContaining({ message: 'passed' })
]); ]);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([ expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([
'failed' jasmine.objectContaining({ message: 'failed' })
]); ]);
}); });
it('forwards late expectation failures to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const spec = new jasmineUnderTest.Spec({
onLateError,
queueableFn: { fn: function() {} }
});
const data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: new Error('nope')
};
spec.reportedDone = true;
spec.addExpectationResult(false, data, true);
expect(onLateError).toHaveBeenCalledWith(
jasmine.objectContaining({
message: jasmine.stringMatching(/^Error: nope/)
})
);
expect(spec.result.failedExpectations).toEqual([]);
});
it('does not forward non-late expectation failures to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const spec = new jasmineUnderTest.Spec({
onLateError,
queueableFn: { fn: function() {} }
});
const data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: new Error('nope')
};
spec.addExpectationResult(false, data, true);
expect(onLateError).not.toHaveBeenCalled();
});
it('forwards late handleException calls to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const spec = new jasmineUnderTest.Spec({
onLateError,
queueableFn: { fn: function() {} }
});
spec.reportedDone = true;
spec.handleException(new Error('oops'));
expect(onLateError).toHaveBeenCalledWith(
jasmine.objectContaining({
message: jasmine.stringMatching(/^Error: oops/)
})
);
expect(spec.result.failedExpectations).toEqual([]);
});
it('does not forward non-late handleException calls to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const spec = new jasmineUnderTest.Spec({
onLateError,
queueableFn: { fn: function() {} }
});
const error = new Error('oops');
spec.handleException(error);
expect(onLateError).not.toHaveBeenCalled();
expect(spec.result.failedExpectations.length).toEqual(1);
});
it('clears the reportedDone flag when reset', function() {
const spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
spec.reportedDone = true;
spec.reset();
expect(spec.reportedDone).toBeFalse();
});
it('does not throw an ExpectationFailed error when handling an error', function() { it('does not throw an ExpectationFailed error when handling an error', function() {
const resultCallback = jasmine.createSpy('resultCallback'), const resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }, queueableFn: { fn: function() {} },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: function(attrs) { queueRunnerFactory: function(attrs) {
attrs.onComplete(); attrs.onComplete();
}, },
@@ -418,7 +496,7 @@ describe('Spec', function() {
throwOnExpectationFailure: true throwOnExpectationFailure: true
}); });
spec.onException('failing exception'); spec.handleException('failing exception');
}); });
it('can return its full name', function() { it('can return its full name', function() {
@@ -483,25 +561,23 @@ describe('Spec', function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }, queueableFn: { fn: function() {} },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner, queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback resultCallback: resultCallback
}); });
spec.onException('foo'); spec.handleException('foo');
spec.execute(); spec.execute();
const args = fakeQueueRunner.calls.mostRecent().args[0]; const args = fakeQueueRunner.calls.mostRecent().args[0];
args.queueableFns[args.queueableFns.length - 1].fn(); args.queueableFns[args.queueableFns.length - 1].fn();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([ expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([
{ {
error: 'foo', message: 'foo thrown',
matcherName: '', matcherName: '',
passed: false, passed: false,
expected: '', expected: '',
actual: '' actual: '',
stack: null
} }
]); ]);
}); });
@@ -511,14 +587,11 @@ describe('Spec', function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }, queueableFn: { fn: function() {} },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner, queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback resultCallback: resultCallback
}); });
spec.onException(new jasmineUnderTest.errors.ExpectationFailed()); spec.handleException(new jasmineUnderTest.errors.ExpectationFailed());
spec.execute(); spec.execute();
const args = fakeQueueRunner.calls.mostRecent().args[0]; const args = fakeQueueRunner.calls.mostRecent().args[0];
@@ -636,7 +709,7 @@ describe('Spec', function() {
resultCallback: resultCallback, resultCallback: resultCallback,
queueRunnerFactory: function(config) { queueRunnerFactory: function(config) {
spec.debugLog('msg'); spec.debugLog('msg');
spec.onException(new Error('nope')); spec.handleException(new Error('nope'));
for (const fn of config.queueableFns) { for (const fn of config.queueableFns) {
fn.fn(); fn.fn();
} }

View File

@@ -106,9 +106,9 @@ describe('SpyStrategy', function() {
it('allows a fake async function to be called instead', function(done) { it('allows a fake async function to be called instead', function(done) {
const originalFn = jasmine.createSpy('original'), const originalFn = jasmine.createSpy('original'),
fakeFn = jasmine fakeFn = jasmine.createSpy('fake').and.callFake(async () => {
.createSpy('fake') return 67;
.and.callFake(eval('async () => { return 67; }')), }),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }); spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.callFake(fakeFn); spyStrategy.callFake(fakeFn);

View File

@@ -71,20 +71,9 @@ describe('Suite', function() {
suite.beforeAll(outerBefore); suite.beforeAll(outerBefore);
suite.beforeAll(innerBefore); suite.beforeAll(innerBefore);
function sameInstance(expected) {
return {
asymmetricMatch: function(actual) {
return actual === expected;
},
jasmineToString: function() {
return `<same instance as ${expected}>`;
}
};
}
expect(suite.beforeAllFns).toEqual([ expect(suite.beforeAllFns).toEqual([
{ fn: outerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) }, { fn: outerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) },
{ fn: innerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) } { fn: innerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) }
]); ]);
}); });
@@ -123,13 +112,9 @@ describe('Suite', function() {
}); });
it('has a status of failed if any expectations have failed', function() { it('has a status of failed if any expectations have failed', function() {
const suite = new jasmineUnderTest.Suite({ const suite = new jasmineUnderTest.Suite({});
expectationResultFactory: function() {
return 'hi';
}
});
suite.addExpectationResult(false); suite.addExpectationResult(false, {});
expect(suite.status()).toBe('failed'); expect(suite.status()).toBe('failed');
}); });
@@ -148,28 +133,110 @@ describe('Suite', function() {
it('throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set', function() { it('throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set', function() {
const suite = new jasmineUnderTest.Suite({ const suite = new jasmineUnderTest.Suite({
expectationResultFactory: function(data) {
return data;
},
throwOnExpectationFailure: true throwOnExpectationFailure: true
}); });
expect(function() { expect(function() {
suite.addExpectationResult(false, 'failed'); suite.addExpectationResult(false, { message: 'failed' });
}).toThrowError(jasmineUnderTest.errors.ExpectationFailed); }).toThrowError(jasmineUnderTest.errors.ExpectationFailed);
expect(suite.status()).toBe('failed'); expect(suite.status()).toBe('failed');
expect(suite.result.failedExpectations).toEqual(['failed']); expect(suite.result.failedExpectations).toEqual([
jasmine.objectContaining({ message: 'failed' })
]);
}); });
it('does not add an additional failure when an expectation fails', function() { it('does not add an additional failure when an expectation fails', function() {
const suite = new jasmineUnderTest.Suite({}); const suite = new jasmineUnderTest.Suite({});
suite.onException(new jasmineUnderTest.errors.ExpectationFailed()); suite.handleException(new jasmineUnderTest.errors.ExpectationFailed());
expect(suite.getResult().failedExpectations).toEqual([]); expect(suite.getResult().failedExpectations).toEqual([]);
}); });
it('forwards late expectation failures to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const suite = new jasmineUnderTest.Suite({ onLateError });
const data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: new Error('nope')
};
suite.reportedDone = true;
suite.addExpectationResult(false, data, true);
expect(onLateError).toHaveBeenCalledWith(
jasmine.objectContaining({
message: jasmine.stringMatching(/^Error: nope/)
})
);
expect(suite.result.failedExpectations).toEqual([]);
});
it('does not forward non-late expectation failures to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const suite = new jasmineUnderTest.Suite({
onLateError
});
const data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: new Error('nope')
};
suite.addExpectationResult(false, data, true);
expect(onLateError).not.toHaveBeenCalled();
expect(suite.result.failedExpectations.length).toEqual(1);
});
it('forwards late handleException calls to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const suite = new jasmineUnderTest.Suite({
onLateError
});
const error = new Error('oops');
suite.reportedDone = true;
suite.handleException(error);
expect(onLateError).toHaveBeenCalledWith(
jasmine.objectContaining({
message: jasmine.stringMatching(/^Error: oops/)
})
);
expect(suite.result.failedExpectations).toEqual([]);
});
it('does not forward non-late handleException calls to onLateError', function() {
const onLateError = jasmine.createSpy('onLateError');
const suite = new jasmineUnderTest.Suite({
onLateError
});
const error = new Error('oops');
suite.handleException(error);
expect(onLateError).not.toHaveBeenCalled();
expect(suite.result.failedExpectations.length).toEqual(1);
});
it('clears the reportedDone flag when reset', function() {
const suite = new jasmineUnderTest.Suite({
queueableFn: { fn: function() {} }
});
suite.reportedDone = true;
suite.reset();
expect(suite.reportedDone).toBeFalse();
});
it('calls timer to compute duration', function() { it('calls timer to compute duration', function() {
const suite = new jasmineUnderTest.Suite({ const suite = new jasmineUnderTest.Suite({
env: env, env: env,
@@ -261,12 +328,8 @@ describe('Suite', function() {
}); });
it('should reset the failedExpectations', function() { it('should reset the failedExpectations', function() {
const suite = new jasmineUnderTest.Suite({ const suite = new jasmineUnderTest.Suite({});
expectationResultFactory: function(error) { suite.handleException(new Error());
return error;
}
});
suite.onException(new Error());
suite.reset(); suite.reset();

View File

@@ -0,0 +1,30 @@
describe('Is', function() {
it('passes for primitives that are ===', function() {
const exactly = new jasmineUnderTest.Is(17);
expect(exactly.asymmetricMatch(17)).toBeTrue();
});
it('fails for primitives that are not ===', function() {
const exactly = new jasmineUnderTest.Is(42);
expect(exactly.asymmetricMatch('42')).toBeFalse();
});
it('passes for the same object instance', function() {
const obj = {};
const exactly = new jasmineUnderTest.Is(obj);
expect(exactly.asymmetricMatch(obj)).toBeTrue();
});
it('fails for different object instances, even if they are deep value equal', function() {
const exactly = new jasmineUnderTest.Is({});
expect(exactly.asymmetricMatch({})).toBeFalse();
});
it('describes itself for use in diffs and pretty printing', function() {
const exactly = new jasmineUnderTest.Is({ foo: ['bar'] });
const pp = jasmineUnderTest.basicPrettyPrinter_;
expect(exactly.jasmineToString(pp)).toEqual(
"<jasmine.is(Object({ foo: [ 'bar' ] }))>"
);
});
});

View File

@@ -22,56 +22,38 @@ describe('buildExpectationResult', function() {
expect(result.message).toBe('some-value'); expect(result.message).toBe('some-value');
}); });
it('delegates message formatting to the provided formatter if there was an Error', function() { describe('When the error property is provided', function() {
const fakeError = { message: 'foo' }, it('sets the message to the formatted error', function() {
messageFormatter = jasmine const result = jasmineUnderTest.buildExpectationResult({
.createSpy('exception message formatter') passed: false,
.and.returnValue(fakeError.message); error: { message: 'foo', fileName: 'somefile.js' }
});
const result = jasmineUnderTest.buildExpectationResult({ expect(result.message).toEqual('foo in somefile.js');
passed: false,
error: fakeError,
messageFormatter: messageFormatter
}); });
expect(messageFormatter).toHaveBeenCalledWith(fakeError); it('delegates stack formatting to the provided formatter', function() {
expect(result.message).toEqual('foo'); const result = jasmineUnderTest.buildExpectationResult({
passed: false,
error: { stack: 'foo', extra: 'wombat' }
});
expect(result.stack).toEqual(
"error properties: Object({ extra: 'wombat' })\nfoo"
);
});
}); });
it('delegates stack formatting to the provided formatter if there was an Error', function() { describe('When the errorForStack property is provided', function() {
const fakeError = { stack: 'foo' }, it('builds the stack trace using errorForStack instead of Error', function() {
stackFormatter = jasmine const result = jasmineUnderTest.buildExpectationResult({
.createSpy('stack formatter') passed: false,
.and.returnValue(fakeError.stack); errorForStack: { stack: 'foo' },
error: { stack: 'bar' }
});
const result = jasmineUnderTest.buildExpectationResult({ expect(result.stack).toEqual('bar');
passed: false,
error: fakeError,
stackFormatter: stackFormatter
}); });
expect(stackFormatter).toHaveBeenCalledWith(fakeError, {
omitMessage: true
});
expect(result.stack).toEqual('foo');
});
it('delegates stack formatting to the provided formatter if there was a provided errorForStack', function() {
const fakeError = { stack: 'foo' },
stackFormatter = jasmine
.createSpy('stack formatter')
.and.returnValue(fakeError.stack);
const result = jasmineUnderTest.buildExpectationResult({
passed: false,
errorForStack: fakeError,
stackFormatter: stackFormatter
});
expect(stackFormatter).toHaveBeenCalledWith(fakeError, {
omitMessage: true
});
expect(result.stack).toEqual('foo');
}); });
it('matcherName returns passed matcherName', function() { it('matcherName returns passed matcherName', function() {

View File

@@ -1,55 +1,57 @@
describe('Asymmetric equality testers (Integration)', function() { describe('Asymmetric equality testers (Integration)', function() {
function verifyPasses(expectations) { function verifyPasses(expectations) {
it('passes', function(done) { it('passes', async function() {
const env = new jasmineUnderTest.Env(); const env = new jasmineUnderTest.Env();
env.it('a spec', function() { env.it('a spec', function() {
expectations(env); expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
expect(result.passedExpectations.length) await env.execute();
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
expect(result.passedExpectations.length)
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
}); });
} }
function verifyFails(expectations) { function verifyFails(expectations) {
it('fails', function(done) { it('fails', async function() {
const env = new jasmineUnderTest.Env(); const env = new jasmineUnderTest.Env();
env.it('a spec', function() { env.it('a spec', function() {
expectations(env); expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext(
'Failed with a thrown error rather than a matcher failure'
)
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext('Failed with a thrown error rather than a matcher failure')
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
} }

View File

@@ -10,7 +10,7 @@ describe('Custom Matchers (Integration)', function() {
env.cleanup_(); env.cleanup_();
}); });
it('allows adding more matchers local to a spec', function(done) { it('allows adding more matchers local to a spec', async function() {
env.it('spec defining a custom matcher', function() { env.it('spec defining a custom matcher', function() {
env.addMatchers({ env.addMatchers({
matcherForSpec: function() { matcherForSpec: function() {
@@ -37,20 +37,18 @@ describe('Custom Matchers (Integration)', function() {
}); });
const specDoneSpy = jasmine.createSpy('specDoneSpy'); const specDoneSpy = jasmine.createSpy('specDoneSpy');
const expectations = function() {
const firstSpecResult = specDoneSpy.calls.first().args[0];
expect(firstSpecResult.status).toEqual('failed');
expect(firstSpecResult.failedExpectations[0].message).toEqual(
'matcherForSpec: actual: zzz; expected: yyy'
);
done();
};
env.addReporter({ specDone: specDoneSpy }); env.addReporter({ specDone: specDoneSpy });
env.execute(null, expectations); await env.execute();
const firstSpecResult = specDoneSpy.calls.first().args[0];
expect(firstSpecResult.status).toEqual('failed');
expect(firstSpecResult.failedExpectations[0].message).toEqual(
'matcherForSpec: actual: zzz; expected: yyy'
);
}); });
it('passes the spec if the custom matcher passes', function(done) { it('passes the spec if the custom matcher passes', async function() {
env.it('spec using custom matcher', function() { env.it('spec using custom matcher', function() {
env.addMatchers({ env.addMatchers({
toBeReal: function() { toBeReal: function() {
@@ -65,15 +63,16 @@ describe('Custom Matchers (Integration)', function() {
env.expect(true).toBeReal(); env.expect(true).toBeReal();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
}; await env.execute();
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
}); });
it('passes the spec if the custom equality matcher passes for types nested inside asymmetric equality testers', function(done) { it('passes the spec if the custom equality matcher passes for types nested inside asymmetric equality testers', async function() {
env.it('spec using custom equality matcher', function() { env.it('spec using custom equality matcher', function() {
const customEqualityFn = function(a, b) { const customEqualityFn = function(a, b) {
// All "foo*" strings match each other. // All "foo*" strings match each other.
@@ -99,15 +98,16 @@ describe('Custom Matchers (Integration)', function() {
.toEqual(jasmineUnderTest.arrayWithExactContents(['fooBar'])); .toEqual(jasmineUnderTest.arrayWithExactContents(['fooBar']));
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
}; await env.execute();
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
}); });
it('displays an appropriate failure message if a custom equality matcher fails', function(done) { it('displays an appropriate failure message if a custom equality matcher fails', async function() {
env.it('spec using custom equality matcher', function() { env.it('spec using custom equality matcher', function() {
const customEqualityFn = function(a, b) { const customEqualityFn = function(a, b) {
// "foo" is not equal to anything // "foo" is not equal to anything
@@ -120,18 +120,19 @@ describe('Custom Matchers (Integration)', function() {
env.expect({ foo: 'foo' }).toEqual({ foo: 'foo' }); env.expect({ foo: 'foo' }).toEqual({ foo: 'foo' });
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations[0].message).toEqual( await env.execute();
"Expected $.foo = 'foo' to equal 'foo'."
);
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations[0].message).toEqual(
"Expected $.foo = 'foo' to equal 'foo'."
);
}); });
it('uses the negative compare function for a negative comparison, if provided', function(done) { it('uses the negative compare function for a negative comparison, if provided', async function() {
env.it('spec with custom negative comparison matcher', function() { env.it('spec with custom negative comparison matcher', function() {
env.addMatchers({ env.addMatchers({
toBeReal: function() { toBeReal: function() {
@@ -149,15 +150,16 @@ describe('Custom Matchers (Integration)', function() {
env.expect(true).not.toBeReal(); env.expect(true).not.toBeReal();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
}; await env.execute();
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
}); });
it('generates messages with the same rules as built in matchers absent a custom message', function(done) { it('generates messages with the same rules as built in matchers absent a custom message', async function() {
env.it('spec with an expectation', function() { env.it('spec with an expectation', function() {
env.addMatchers({ env.addMatchers({
toBeReal: function() { toBeReal: function() {
@@ -172,17 +174,18 @@ describe('Custom Matchers (Integration)', function() {
env.expect('a').toBeReal(); env.expect('a').toBeReal();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.failedExpectations[0].message).toEqual( env.addReporter(reporter);
"Expected 'a' to be real." await env.execute();
);
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.failedExpectations[0].message).toEqual(
"Expected 'a' to be real."
);
}); });
it('passes the expected and actual arguments to the comparison function', function(done) { it('passes the expected and actual arguments to the comparison function', async function() {
const argumentSpy = jasmine const argumentSpy = jasmine
.createSpy('argument spy') .createSpy('argument spy')
.and.returnValue({ pass: true }); .and.returnValue({ pass: true });
@@ -199,17 +202,13 @@ describe('Custom Matchers (Integration)', function() {
env.expect(true).toBeReal('arg1', 'arg2'); env.expect(true).toBeReal('arg1', 'arg2');
}); });
const specExpectations = function() { await env.execute();
expect(argumentSpy).toHaveBeenCalledWith(true); expect(argumentSpy).toHaveBeenCalledWith(true);
expect(argumentSpy).toHaveBeenCalledWith(true, 'arg'); expect(argumentSpy).toHaveBeenCalledWith(true, 'arg');
expect(argumentSpy).toHaveBeenCalledWith(true, 'arg1', 'arg2'); expect(argumentSpy).toHaveBeenCalledWith(true, 'arg1', 'arg2');
};
env.addReporter({ specDone: specExpectations });
env.execute(null, done);
}); });
it('passes the jasmine utility to the matcher factory', function(done) { it('passes the jasmine utility to the matcher factory', async function() {
const matcherFactory = function() { const matcherFactory = function() {
return { return {
compare: function() { compare: function() {
@@ -229,17 +228,13 @@ describe('Custom Matchers (Integration)', function() {
env.expect(true).toBeReal(); env.expect(true).toBeReal();
}); });
const specExpectations = function() { await env.execute();
expect(matcherFactorySpy).toHaveBeenCalledWith( expect(matcherFactorySpy).toHaveBeenCalledWith(
jasmine.any(jasmineUnderTest.MatchersUtil) jasmine.any(jasmineUnderTest.MatchersUtil)
); );
};
env.addReporter({ specDone: specExpectations });
env.execute(null, done);
}); });
it('provides custom equality testers to the matcher factory via matchersUtil', function(done) { it('provides custom equality testers to the matcher factory via matchersUtil', async function() {
const matcherFactory = function(matchersUtil) { const matcherFactory = function(matchersUtil) {
return { return {
compare: function(actual, expected) { compare: function(actual, expected) {
@@ -262,12 +257,13 @@ describe('Custom Matchers (Integration)', function() {
env.expect([1, 2]).toBeArrayWithFirstElement('1'); env.expect([1, 2]).toBeArrayWithFirstElement('1');
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(customEqualityFn).toHaveBeenCalledWith(1, '1'); env.addReporter(reporter);
expect(result.failedExpectations).toEqual([]); await env.execute();
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(customEqualityFn).toHaveBeenCalledWith(1, '1');
expect(result.failedExpectations).toEqual([]);
}); });
}); });

View File

@@ -6,7 +6,7 @@ describe('Custom object formatters', function() {
env.configure({ random: false }); env.configure({ random: false });
}); });
it('scopes custom object formatters to a spec', function(done) { it('scopes custom object formatters to a spec', async function() {
env.it('a spec with custom pretty-printer', function() { env.it('a spec with custom pretty-printer', function() {
env.addCustomObjectFormatter(function(obj) { env.addCustomObjectFormatter(function(obj) {
return 'custom(' + obj + ')'; return 'custom(' + obj + ')';
@@ -22,21 +22,19 @@ describe('Custom object formatters', function() {
const specDone = function(result) { const specDone = function(result) {
specResults.push(result); specResults.push(result);
}; };
const expectations = function() {
expect(specResults[0].failedExpectations[0].message).toEqual(
'Expected custom(42) to be undefined.'
);
expect(specResults[1].failedExpectations[0].message).toEqual(
'Expected 42 to be undefined.'
);
done();
};
env.addReporter({ specDone: specDone }); env.addReporter({ specDone: specDone });
env.execute(null, expectations); await env.execute();
expect(specResults[0].failedExpectations[0].message).toEqual(
'Expected custom(42) to be undefined.'
);
expect(specResults[1].failedExpectations[0].message).toEqual(
'Expected 42 to be undefined.'
);
}); });
it('scopes custom object formatters to a suite', function(done) { it('scopes custom object formatters to a suite', async function() {
env.it('a spec without custom pretty-printer', function() { env.it('a spec without custom pretty-printer', function() {
env.expect(42).toBeUndefined(); env.expect(42).toBeUndefined();
}); });
@@ -57,18 +55,16 @@ describe('Custom object formatters', function() {
const specDone = function(result) { const specDone = function(result) {
specResults.push(result); specResults.push(result);
}; };
const expectations = function() {
expect(specResults[0].failedExpectations[0].message).toEqual(
'Expected 42 to be undefined.'
);
expect(specResults[1].failedExpectations[0].message).toEqual(
'Expected custom(42) to be undefined.'
);
done();
};
env.addReporter({ specDone: specDone }); env.addReporter({ specDone: specDone });
env.execute(null, expectations); await env.execute();
expect(specResults[0].failedExpectations[0].message).toEqual(
'Expected 42 to be undefined.'
);
expect(specResults[1].failedExpectations[0].message).toEqual(
'Expected custom(42) to be undefined.'
);
}); });
it('throws an exception if you try to add a custom object formatter outside a runable', function() { it('throws an exception if you try to add a custom object formatter outside a runable', function() {

View File

@@ -10,7 +10,7 @@ describe('Deprecation (integration)', function() {
env.cleanup_(); env.cleanup_();
}); });
it('reports a deprecation on the top suite', function(done) { it('reports a deprecation on the top suite', async function() {
const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']); const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -20,24 +20,23 @@ describe('Deprecation (integration)', function() {
}); });
env.it('a spec', function() {}); env.it('a spec', function() {});
env.execute(null, function() { await env.execute();
expect(reporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.jasmineDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledWith( );
jasmine.stringMatching(/^DEPRECATION: the message/) expect(console.error).toHaveBeenCalledWith(
); jasmine.stringMatching(/^DEPRECATION: the message/)
done(); );
});
}); });
it('reports a deprecation on a descendent suite', function(done) { it('reports a deprecation on a descendent suite', async function() {
const reporter = jasmine.createSpyObj('reporter', ['suiteDone']); const reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -49,26 +48,23 @@ describe('Deprecation (integration)', function() {
env.it('a spec', function() {}); env.it('a spec', function() {});
}); });
env.execute(null, function() { await env.execute();
expect(reporter.suiteDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.suiteDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledWith( );
jasmine.stringMatching( expect(console.error).toHaveBeenCalledWith(
/^DEPRECATION: the message \(in suite: a suite\)/ jasmine.stringMatching(/^DEPRECATION: the message \(in suite: a suite\)/)
) );
);
done();
});
}); });
it('reports a deprecation on a spec', function(done) { it('reports a deprecation on a spec', async function() {
const reporter = jasmine.createSpyObj('reporter', ['specDone']); const reporter = jasmine.createSpyObj('reporter', ['specDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -79,26 +75,25 @@ describe('Deprecation (integration)', function() {
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.specDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.specDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledWith( );
jasmine.stringMatching( expect(console.error).toHaveBeenCalledWith(
/^DEPRECATION: the message \(in spec: a suite a spec\)/ jasmine.stringMatching(
) /^DEPRECATION: the message \(in spec: a suite a spec\)/
); )
done(); );
});
}); });
it('omits the suite or spec context when ignoreRunnable is true', function(done) { it('omits the suite or spec context when ignoreRunnable is true', async function() {
const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']); const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -107,27 +102,26 @@ describe('Deprecation (integration)', function() {
env.deprecated('the message', { ignoreRunnable: true }); env.deprecated('the message', { ignoreRunnable: true });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.jasmineDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledWith( );
jasmine.stringMatching(/the message/) expect(console.error).toHaveBeenCalledWith(
); jasmine.stringMatching(/the message/)
expect(console.error).not.toHaveBeenCalledWith( );
jasmine.stringMatching(/a spec/) expect(console.error).not.toHaveBeenCalledWith(
); jasmine.stringMatching(/a spec/)
done(); );
});
}); });
it('includes the stack trace', function(done) { it('includes the stack trace', async function() {
const reporter = jasmine.createSpyObj('reporter', ['specDone']); const reporter = jasmine.createSpyObj('reporter', ['specDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -138,25 +132,24 @@ describe('Deprecation (integration)', function() {
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.specDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.specDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
stack: jasmine.stringMatching(/DeprecationSpec.js/) jasmine.objectContaining({
}) stack: jasmine.stringMatching(/DeprecationSpec.js/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalled(); );
expect(console.error.calls.argsFor(0)[0].replace(/\n/g, 'NL')).toMatch( expect(console.error).toHaveBeenCalled();
/^DEPRECATION: the message \(in spec: a suite a spec\)NL.*DeprecationSpec.js/ expect(console.error.calls.argsFor(0)[0].replace(/\n/g, 'NL')).toMatch(
); /^DEPRECATION: the message \(in spec: a suite a spec\)NL.*DeprecationSpec.js/
done(); );
});
}); });
it('excludes the stack trace when omitStackTrace is true', function(done) { it('excludes the stack trace when omitStackTrace is true', async function() {
const reporter = jasmine.createSpyObj('reporter', ['specDone']); const reporter = jasmine.createSpyObj('reporter', ['specDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -167,25 +160,24 @@ describe('Deprecation (integration)', function() {
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.specDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.specDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
stack: jasmine.falsy() jasmine.objectContaining({
}) stack: jasmine.falsy()
] })
}) ]
); })
expect(console.error).toHaveBeenCalled(); );
expect(console.error).not.toHaveBeenCalledWith( expect(console.error).toHaveBeenCalled();
jasmine.stringMatching(/DeprecationSpec.js/) expect(console.error).not.toHaveBeenCalledWith(
); jasmine.stringMatching(/DeprecationSpec.js/)
done(); );
});
}); });
it('emits a given deprecation only once', function(done) { it('emits a given deprecation only once', async function() {
const reporter = jasmine.createSpyObj('reporter', [ const reporter = jasmine.createSpyObj('reporter', [
'specDone', 'specDone',
'suiteDone' 'suiteDone'
@@ -205,43 +197,40 @@ describe('Deprecation (integration)', function() {
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.suiteDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.suiteDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
// only one deprecationWarnings: [
jasmine.objectContaining({ // only one
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(reporter.specDone).toHaveBeenCalledWith( );
jasmine.objectContaining({ expect(reporter.specDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
// only the other one deprecationWarnings: [
jasmine.objectContaining({ // only the other one
message: jasmine.stringMatching(/^a different message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^a different message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledTimes(2); );
expect(console.error).toHaveBeenCalledWith( expect(console.error).toHaveBeenCalledTimes(2);
jasmine.stringMatching( expect(console.error).toHaveBeenCalledWith(
/^DEPRECATION: the message \(in suite: a suite\)/ jasmine.stringMatching(/^DEPRECATION: the message \(in suite: a suite\)/)
) );
); expect(console.error).toHaveBeenCalledWith(
expect(console.error).toHaveBeenCalledWith( jasmine.stringMatching(
jasmine.stringMatching( /^DEPRECATION: a different message \(in spec: a suite a spec\)/
/^DEPRECATION: a different message \(in spec: a suite a spec\)/ )
) );
);
done();
});
}); });
it('emits a given deprecation each time when config.verboseDeprecations is true', function(done) { it('emits a given deprecation each time when config.verboseDeprecations is true', async function() {
const reporter = jasmine.createSpyObj('reporter', [ const reporter = jasmine.createSpyObj('reporter', [
'specDone', 'specDone',
'suiteDone' 'suiteDone'
@@ -262,46 +251,45 @@ describe('Deprecation (integration)', function() {
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.suiteDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.suiteDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}), message: jasmine.stringMatching(/^the message/)
jasmine.objectContaining({ }),
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(reporter.specDone).toHaveBeenCalledWith( );
jasmine.objectContaining({ expect(reporter.specDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledTimes(3); );
expect(console.error.calls.argsFor(0)[0]).toMatch( expect(console.error).toHaveBeenCalledTimes(3);
/^DEPRECATION: the message \(in suite: a suite\)/ expect(console.error.calls.argsFor(0)[0]).toMatch(
); /^DEPRECATION: the message \(in suite: a suite\)/
expect(console.error.calls.argsFor(1)[0]).toMatch( );
/^DEPRECATION: the message \(in suite: a suite\)/ expect(console.error.calls.argsFor(1)[0]).toMatch(
); /^DEPRECATION: the message \(in suite: a suite\)/
expect(console.error.calls.argsFor(2)[0]).toMatch( );
/^DEPRECATION: the message \(in spec: a suite a spec\)/ expect(console.error.calls.argsFor(2)[0]).toMatch(
); /^DEPRECATION: the message \(in spec: a suite a spec\)/
expect(console.error.calls.argsFor(2)[0]).toMatch( );
/^DEPRECATION: the message \(in spec: a suite a spec\)/ expect(console.error.calls.argsFor(2)[0]).toMatch(
); /^DEPRECATION: the message \(in spec: a suite a spec\)/
done(); );
});
}); });
it('handles deprecations that occur before execute() is called', function(done) { it('handles deprecations that occur before execute() is called', async function() {
const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']); const reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
env.addReporter(reporter); env.addReporter(reporter);
spyOn(console, 'error'); spyOn(console, 'error');
@@ -309,20 +297,19 @@ describe('Deprecation (integration)', function() {
env.deprecated('the message'); env.deprecated('the message');
env.it('a spec', function() {}); env.it('a spec', function() {});
env.execute(null, function() { await env.execute();
expect(reporter.jasmineDone).toHaveBeenCalledWith(
jasmine.objectContaining({ expect(reporter.jasmineDone).toHaveBeenCalledWith(
deprecationWarnings: [ jasmine.objectContaining({
jasmine.objectContaining({ deprecationWarnings: [
message: jasmine.stringMatching(/^the message/) jasmine.objectContaining({
}) message: jasmine.stringMatching(/^the message/)
] })
}) ]
); })
expect(console.error).toHaveBeenCalledWith( );
jasmine.stringMatching(/^DEPRECATION: the message/) expect(console.error).toHaveBeenCalledWith(
); jasmine.stringMatching(/^DEPRECATION: the message/)
done(); );
});
}); });
}); });

View File

@@ -454,55 +454,319 @@ describe('Env integration', function() {
env.execute(null, assertions); env.execute(null, assertions);
}); });
it('copes with async failures after done has been called', function(done) { describe('Handling async errors', function() {
const global = { it('routes async errors to a running spec', async function() {
setTimeout: function(fn, delay) { const global = {
return setTimeout(fn, delay); setTimeout: function(fn, delay) {
}, return setTimeout(fn, delay);
clearTimeout: function(fn, delay) { },
clearTimeout(fn, delay); clearTimeout: function(fn, delay) {
} clearTimeout(fn, delay);
}; }
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global); };
env.cleanup_(); spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
env = new jasmineUnderTest.Env(); env.cleanup_();
const reporter = jasmine.createSpyObj('fakeReporter', [ env = new jasmineUnderTest.Env();
'specDone', const reporter = jasmine.createSpyObj('fakeReporter', [
'suiteDone' 'specDone',
]); 'suiteDone'
]);
const assertions = function() { env.addReporter(reporter);
expect(reporter.specDone).not.toHaveFailedExpectationsForRunnable(
env.describe('A suite', function() {
env.it('fails', function(specDone) {
setTimeout(function() {
global.onerror('fail');
specDone();
});
});
});
await env.execute();
expect(reporter.specDone).toHaveFailedExpectationsForRunnable(
'A suite fails', 'A suite fails',
['fail thrown'] ['fail thrown']
); );
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable( });
'A suite',
['fail thrown']
);
done();
};
env.addReporter(reporter); describe('When the running spec has reported specDone', function() {
it('routes async errors to an ancestor suite', async function() {
const global = {
setTimeout: function(fn, delay) {
return setTimeout(fn, delay);
},
clearTimeout: function(fn) {
clearTimeout(fn);
}
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
env.fdescribe('A suite', function() { const realClearStack = jasmineUnderTest.getClearStack(global);
env.it('fails', function(specDone) { const clearStackCallbacks = {};
setTimeout(function() { let clearStackCallCount = 0;
specDone(); spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
clearStackCallCount++;
if (clearStackCallbacks[clearStackCallCount]) {
clearStackCallbacks[clearStackCallCount]();
}
realClearStack(fn);
});
env.cleanup_();
env = new jasmineUnderTest.Env();
let suiteErrors = [];
env.addReporter({
suiteDone: function(result) {
const messages = result.failedExpectations.map(e => e.message);
suiteErrors = suiteErrors.concat(messages);
},
specDone: function() {
clearStackCallbacks[clearStackCallCount + 1] = function() {
global.onerror('fail at the end of the reporter queue');
};
clearStackCallbacks[clearStackCallCount + 2] = function() {
global.onerror('fail at the end of the spec queue');
};
}
});
env.describe('A suite', function() {
env.it('is finishing when the failure occurs', function() {});
});
await env.execute();
expect(suiteErrors).toEqual([
'fail at the end of the reporter queue thrown',
'fail at the end of the spec queue thrown'
]);
});
});
it('routes async errors to a running suite', function(done) {
const global = {
setTimeout: function(fn, delay) {
return setTimeout(fn, delay);
},
clearTimeout: function(fn, delay) {
clearTimeout(fn, delay);
}
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
env.cleanup_();
env = new jasmineUnderTest.Env();
const reporter = jasmine.createSpyObj('fakeReporter', [
'specDone',
'suiteDone'
]);
const assertions = function() {
expect(reporter.specDone).not.toHaveFailedExpectationsForRunnable(
'A suite fails',
['fail thrown']
);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable(
'A suite',
['fail thrown']
);
done();
};
env.addReporter(reporter);
env.fdescribe('A suite', function() {
env.it('fails', function(specDone) {
setTimeout(function() { setTimeout(function() {
specDone();
setTimeout(function() { setTimeout(function() {
global.onerror('fail'); setTimeout(function() {
global.onerror('fail');
});
}); });
}); });
}); });
}); });
env.describe('Ignored', function() {
env.it('is not run', function() {});
});
env.execute(null, assertions);
}); });
env.describe('Ignored', function() { describe('When the running suite has reported suiteDone', function() {
env.it('is not run', function() {}); it('routes async errors to an ancestor suite', async function() {
const global = {
setTimeout: function(fn, delay) {
return setTimeout(fn, delay);
},
clearTimeout: function(fn, delay) {
clearTimeout(fn, delay);
}
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
const realClearStack = jasmineUnderTest.getClearStack(global);
const clearStackCallbacks = {};
let clearStackCallCount = 0;
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
clearStackCallCount++;
if (clearStackCallbacks[clearStackCallCount]) {
clearStackCallbacks[clearStackCallCount]();
}
realClearStack(fn);
});
env.cleanup_();
env = new jasmineUnderTest.Env();
let suiteErrors = [];
env.addReporter({
suiteDone: function(result) {
const messages = result.failedExpectations.map(e => e.message);
suiteErrors = suiteErrors.concat(messages);
if (result.description === 'A nested suite') {
clearStackCallbacks[clearStackCallCount + 1] = function() {
global.onerror('fail at the end of the reporter queue');
};
clearStackCallbacks[clearStackCallCount + 2] = function() {
global.onerror('fail at the end of the suite queue');
};
}
}
});
env.describe('A suite', function() {
env.describe('A nested suite', function() {
env.it('a spec', function() {});
});
});
await env.execute();
expect(suiteErrors).toEqual([
'fail at the end of the reporter queue thrown',
'fail at the end of the suite queue thrown'
]);
});
}); });
env.execute(null, assertions); describe('When the env has started reporting jasmineDone', function() {
it('logs the error to the console', async function() {
const global = {
setTimeout: function(fn, delay) {
return setTimeout(fn, delay);
},
clearTimeout: function(fn, delay) {
clearTimeout(fn, delay);
}
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
env.cleanup_();
env = new jasmineUnderTest.Env();
spyOn(console, 'error');
env.addReporter({
jasmineDone: function() {
global.onerror('a very late error');
}
});
env.it('a spec', function() {});
await env.execute();
/* eslint-disable-next-line no-console */
expect(console.error).toHaveBeenCalledWith(
'Jasmine received a result after the suite finished:'
);
/* eslint-disable-next-line no-console */
expect(console.error).toHaveBeenCalledWith(
jasmine.objectContaining({
message: 'a very late error thrown',
globalErrorType: 'afterAll'
})
);
});
});
it('routes all errors that occur during stack clearing somewhere', async function() {
const global = {
setTimeout: function(fn, delay) {
return setTimeout(fn, delay);
},
clearTimeout: function(fn) {
clearTimeout(fn);
}
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
const realClearStack = jasmineUnderTest.getClearStack(global);
let clearStackCallCount = 0;
let jasmineDone = false;
const expectedErrors = [];
const expectedErrorsAfterJasmineDone = [];
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(function(fn) {
clearStackCallCount++;
const msg = `Error in clearStack #${clearStackCallCount}`;
if (jasmineDone) {
expectedErrorsAfterJasmineDone.push(`${msg} thrown`);
} else {
expectedErrors.push(`${msg} thrown`);
}
global.onerror(msg);
realClearStack(fn);
});
spyOn(console, 'error');
env.cleanup_();
env = new jasmineUnderTest.Env();
const receivedErrors = [];
function logErrors(event) {
for (const failure of event.failedExpectations) {
receivedErrors.push(failure.message);
}
}
env.addReporter({
specDone: logErrors,
suiteDone: logErrors,
jasmineDone: function(event) {
jasmineDone = true;
logErrors(event);
}
});
env.describe('A suite', function() {
env.it('is finishing when the failure occurs', function() {});
});
await env.execute();
expect(receivedErrors.length).toEqual(expectedErrors.length);
for (const e of expectedErrors) {
expect(receivedErrors).toContain(e);
}
for (const message of expectedErrorsAfterJasmineDone) {
/* eslint-disable-next-line no-console */
expect(console.error).toHaveBeenCalledWith(
jasmine.objectContaining({ message })
);
}
});
}); });
it('reports multiple calls to done in the top suite as errors', function(done) { it('reports multiple calls to done in the top suite as errors', function(done) {
@@ -539,11 +803,18 @@ describe('Env integration', function() {
}); });
}); });
it('reports multiple calls to done in a non-top suite as errors', function(done) { it('reports multiple calls to done in a non-top suite as errors', async function() {
const reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']); const reporter = jasmine.createSpyObj('fakeReporter', [
'jasmineDone',
'suiteDone'
]);
const message = const message =
"An asynchronous beforeAll or afterAll function called its 'done' " + "An asynchronous beforeAll or afterAll function called its 'done' " +
'callback more than once.\n(in suite: a suite)'; 'callback more than once.\n(in suite: a suite)';
let lateDone;
reporter.suiteDone.and.callFake(function() {
lateDone();
});
env.addReporter(reporter); env.addReporter(reporter);
env.describe('a suite', function() { env.describe('a suite', function() {
@@ -555,31 +826,50 @@ describe('Env integration', function() {
env.afterAll(function(innerDone) { env.afterAll(function(innerDone) {
innerDone(); innerDone();
innerDone(); innerDone();
lateDone = innerDone;
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.jasmineDone).toHaveBeenCalled();
const errors = reporter.jasmineDone.calls.argsFor(0)[0] expect(reporter.suiteDone).toHaveBeenCalled();
.failedExpectations; const suiteErrors = reporter.suiteDone.calls.argsFor(0)[0]
expect(errors.length).toEqual(2); .failedExpectations;
expect(errors[0].message) expect(suiteErrors.length).toEqual(2);
.withContext('suite beforeAll') expect(suiteErrors[0].message)
.toContain(message); .withContext('suite beforeAll')
expect(errors[0].globalErrorType).toEqual('lateError'); .toContain(message);
expect(errors[1].message) expect(suiteErrors[1].message)
.withContext('suite afterAll') .withContext('suite afterAll')
.toContain(message); .toContain(message);
expect(errors[1].globalErrorType).toEqual('lateError');
done(); expect(reporter.jasmineDone).toHaveBeenCalled();
}); const topErrors = reporter.jasmineDone.calls.argsFor(0)[0]
.failedExpectations;
expect(topErrors.length).toEqual(1);
expect(topErrors[0].message)
.withContext('late suite afterAll')
.toContain(message);
expect(topErrors[0].globalErrorType).toEqual('lateError');
expect(topErrors[0].globalErrorType).toEqual('lateError');
}); });
it('reports multiple calls to done in a spec as errors', function(done) { it('reports multiple calls to done in a spec as errors', async function() {
const reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']); const reporter = jasmine.createSpyObj('fakeReporter', [
'specDone',
'suiteDone',
'jasmineDone'
]);
const message = const message =
'An asynchronous spec, beforeEach, or afterEach function called its ' + 'An asynchronous spec, beforeEach, or afterEach function called its ' +
"'done' callback more than once.\n(in spec: a suite a spec)"; "'done' callback more than once.\n(in spec: a suite a spec)";
let lateDone;
reporter.specDone.and.callFake(function() {
lateDone();
});
reporter.suiteDone.and.callFake(function() {
lateDone();
});
env.addReporter(reporter); env.addReporter(reporter);
env.describe('a suite', function() { env.describe('a suite', function() {
@@ -594,28 +884,39 @@ describe('Env integration', function() {
env.afterEach(function(innerDone) { env.afterEach(function(innerDone) {
innerDone(); innerDone();
innerDone(); innerDone();
lateDone = innerDone;
}); });
}); });
env.execute(null, function() { await env.execute();
expect(reporter.jasmineDone).toHaveBeenCalled();
const errors = reporter.jasmineDone.calls.argsFor(0)[0] expect(reporter.specDone).toHaveBeenCalled();
.failedExpectations; const specErrors = reporter.specDone.calls.argsFor(0)[0].failedExpectations;
expect(errors.length).toEqual(3); expect(specErrors.length).toEqual(3);
expect(errors[0].message) expect(specErrors[0].message)
.withContext('error caused by beforeEach') .withContext('error caused by beforeEach')
.toContain(message); .toContain(message);
expect(errors[0].globalErrorType).toEqual('lateError'); expect(specErrors[1].message)
expect(errors[1].message) .withContext('error caused by it')
.withContext('error caused by it') .toContain(message);
.toContain(message); expect(specErrors[2].message)
expect(errors[1].globalErrorType).toEqual('lateError'); .withContext('error caused by afterEach')
expect(errors[2].message) .toContain(message);
.withContext('error caused by afterEach')
.toContain(message); const suiteErrors = reporter.suiteDone.calls.argsFor(0)[0]
expect(errors[2].globalErrorType).toEqual('lateError'); .failedExpectations;
done(); expect(suiteErrors.length).toEqual(1);
}); expect(suiteErrors[0].message)
.withContext('late error caused by afterEach')
.toContain(message);
const topErrors = reporter.jasmineDone.calls.argsFor(0)[0]
.failedExpectations;
expect(topErrors.length).toEqual(1);
expect(topErrors[0].message)
.withContext('really late error caused by afterEach')
.toContain(message);
expect(topErrors[0].globalErrorType).toEqual('lateError');
}); });
it('reports multiple calls to done in reporters as errors', function(done) { it('reports multiple calls to done in reporters as errors', function(done) {
@@ -1320,7 +1621,7 @@ describe('Env integration', function() {
}); });
env.addReporter(reporter); env.addReporter(reporter);
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 5; jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 500;
env.beforeAll(function() { env.beforeAll(function() {
clock.install(); clock.install();
@@ -1331,7 +1632,7 @@ describe('Env integration', function() {
}); });
env.it('spec that should not time out', function(innerDone) { env.it('spec that should not time out', function(innerDone) {
clock.tick(6); clock.tick(1000);
expect(true).toEqual(true); expect(true).toEqual(true);
jasmine.debugLog('Calling realSetTimeout in spec'); jasmine.debugLog('Calling realSetTimeout in spec');
realSetTimeout(function() { realSetTimeout(function() {

View File

@@ -10,156 +10,158 @@ describe('Matchers (Integration)', function() {
}); });
function verifyPasses(expectations) { function verifyPasses(expectations) {
it('passes', function(done) { it('passes', async function() {
env.it('a spec', function() { env.it('a spec', function() {
expectations(env); expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
expect(result.passedExpectations.length) await env.execute();
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
expect(result.passedExpectations.length)
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
}); });
} }
function verifyFails(expectations) { function verifyFails(expectations) {
it('fails', function(done) { it('fails', async function() {
env.it('a spec', function() { env.it('a spec', function() {
expectations(env); expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext(
'Failed with a thrown error rather than a matcher failure'
)
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].message)
.withContext(
'Failed with a thrown type error rather than a matcher failure'
)
.not.toMatch(/^TypeError: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext('Failed with a thrown error rather than a matcher failure')
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].message)
.withContext(
'Failed with a thrown type error rather than a matcher failure'
)
.not.toMatch(/^TypeError: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
} }
function verifyFailsWithCustomObjectFormatters(config) { function verifyFailsWithCustomObjectFormatters(config) {
it('uses custom object formatters', function(done) { it('uses custom object formatters', async function() {
env.it('a spec', function() { env.it('a spec', function() {
env.addCustomObjectFormatter(config.formatter); env.addCustomObjectFormatter(config.formatter);
config.expectations(env); config.expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
config.expectedMessage
);
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
config.expectedMessage
);
}); });
} }
function verifyPassesAsync(expectations) { function verifyPassesAsync(expectations) {
it('passes', function(done) { it('passes', async function() {
env.it('a spec', function() { env.it('a spec', function() {
return expectations(env); return expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('passed'); env.addReporter(reporter);
expect(result.passedExpectations.length) await env.execute();
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('passed');
expect(result.passedExpectations.length)
.withContext('Number of passed expectations')
.toEqual(1);
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(0);
expect(
result.failedExpectations[0] && result.failedExpectations[0].message
)
.withContext('Failure message')
.toBeUndefined();
}); });
} }
function verifyFailsAsync(expectations) { function verifyFailsAsync(expectations) {
it('fails', function(done) { it('fails', async function() {
env.it('a spec', function() { env.it('a spec', function() {
return expectations(env); return expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext(
'Failed with a thrown error rather than a matcher failure'
)
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message)
.withContext('Failed with a thrown error rather than a matcher failure')
.not.toMatch(/^Error: /);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
} }
function verifyFailsWithCustomObjectFormattersAsync(config) { function verifyFailsWithCustomObjectFormattersAsync(config) {
it('uses custom object formatters', function(done) { it('uses custom object formatters', async function() {
const env = new jasmineUnderTest.Env(); const env = new jasmineUnderTest.Env();
env.it('a spec', function() { env.it('a spec', function() {
env.addCustomObjectFormatter(config.formatter); env.addCustomObjectFormatter(config.formatter);
return config.expectations(env); return config.expectations(env);
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
config.expectedMessage
);
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
config.expectedMessage
);
}); });
} }
@@ -753,76 +755,79 @@ describe('Matchers (Integration)', function() {
}); });
describe('When an async matcher is used with .already()', function() { describe('When an async matcher is used with .already()', function() {
it('propagates the matcher result when the promise is resolved', function(done) { it('propagates the matcher result when the promise is resolved', async function() {
env.it('a spec', function() { env.it('a spec', function() {
return env.expectAsync(Promise.resolve()).already.toBeRejected(); return env.expectAsync(Promise.resolve()).already.toBeRejected();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected [object Promise] to be rejected.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected [object Promise] to be rejected.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
it('propagates the matcher result when the promise is rejected', function(done) { it('propagates the matcher result when the promise is rejected', async function() {
env.it('a spec', function() { env.it('a spec', function() {
return env return env
.expectAsync(Promise.reject(new Error('nope'))) .expectAsync(Promise.reject(new Error('nope')))
.already.toBeResolved(); .already.toBeResolved();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected a promise to be resolved but it was ' +
'rejected with Error: nope.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected a promise to be resolved but it was ' +
'rejected with Error: nope.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
it('fails when the promise is pending', function(done) { it('fails when the promise is pending', async function() {
const promise = new Promise(function() {}); const promise = new Promise(function() {});
env.it('a spec', function() { env.it('a spec', function() {
return env.expectAsync(promise).already.toBeResolved(); return env.expectAsync(promise).already.toBeResolved();
}); });
const specExpectations = function(result) { const reporter = jasmine.createSpyObj('reporter', ['specDone']);
expect(result.status).toEqual('failed'); env.addReporter(reporter);
expect(result.failedExpectations.length) await env.execute();
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected a promise to be settled ' +
'(via expectAsync(...).already) but it was pending.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
};
env.addReporter({ specDone: specExpectations }); expect(reporter.specDone).toHaveBeenCalledTimes(1);
env.execute(null, done); const result = reporter.specDone.calls.argsFor(0)[0];
expect(result.status).toEqual('failed');
expect(result.failedExpectations.length)
.withContext('Number of failed expectations')
.toEqual(1);
expect(result.failedExpectations[0].message).toEqual(
'Expected a promise to be settled ' +
'(via expectAsync(...).already) but it was pending.'
);
expect(result.failedExpectations[0].matcherName)
.withContext('Matcher name')
.not.toEqual('');
}); });
}); });
}); });

View File

@@ -1,6 +1,6 @@
describe('DiffBuilder', function() { describe('DiffBuilder', function() {
it('records the actual and expected objects', function() { it('records the actual and expected objects', function() {
const diffBuilder = jasmineUnderTest.DiffBuilder(); const diffBuilder = new jasmineUnderTest.DiffBuilder();
diffBuilder.setRoots({ x: 'actual' }, { x: 'expected' }); diffBuilder.setRoots({ x: 'actual' }, { x: 'expected' });
diffBuilder.recordMismatch(); diffBuilder.recordMismatch();
@@ -10,7 +10,7 @@ describe('DiffBuilder', function() {
}); });
it('prints the path at which the difference was found', function() { it('prints the path at which the difference was found', function() {
const diffBuilder = jasmineUnderTest.DiffBuilder(); const diffBuilder = new jasmineUnderTest.DiffBuilder();
diffBuilder.setRoots({ foo: { x: 'actual' } }, { foo: { x: 'expected' } }); diffBuilder.setRoots({ foo: { x: 'actual' } }, { foo: { x: 'expected' } });
diffBuilder.withPath('foo', function() { diffBuilder.withPath('foo', function() {
@@ -23,7 +23,7 @@ describe('DiffBuilder', function() {
}); });
it('prints multiple messages, separated by newlines', function() { it('prints multiple messages, separated by newlines', function() {
const diffBuilder = jasmineUnderTest.DiffBuilder(); const diffBuilder = new jasmineUnderTest.DiffBuilder();
diffBuilder.setRoots({ foo: 1, bar: 3 }, { foo: 2, bar: 4 }); diffBuilder.setRoots({ foo: 1, bar: 3 }, { foo: 2, bar: 4 });
diffBuilder.withPath('foo', function() { diffBuilder.withPath('foo', function() {
@@ -40,7 +40,7 @@ describe('DiffBuilder', function() {
}); });
it('allows customization of the message', function() { it('allows customization of the message', function() {
const diffBuilder = jasmineUnderTest.DiffBuilder(); const diffBuilder = new jasmineUnderTest.DiffBuilder();
diffBuilder.setRoots({ x: 'bar' }, { x: 'foo' }); diffBuilder.setRoots({ x: 'bar' }, { x: 'foo' });
function darthVaderFormatter(actual, expected, path) { function darthVaderFormatter(actual, expected, path) {
@@ -68,7 +68,7 @@ describe('DiffBuilder', function() {
const prettyPrinter = function(val) { const prettyPrinter = function(val) {
return '|' + val + '|'; return '|' + val + '|';
}, },
diffBuilder = jasmineUnderTest.DiffBuilder({ diffBuilder = new jasmineUnderTest.DiffBuilder({
prettyPrinter: prettyPrinter prettyPrinter: prettyPrinter
}); });
prettyPrinter.customFormat_ = function() {}; prettyPrinter.customFormat_ = function() {};
@@ -86,7 +86,7 @@ describe('DiffBuilder', function() {
it('passes the injected pretty-printer to the diff formatter', function() { it('passes the injected pretty-printer to the diff formatter', function() {
const diffFormatter = jasmine.createSpy('diffFormatter'), const diffFormatter = jasmine.createSpy('diffFormatter'),
prettyPrinter = function() {}, prettyPrinter = function() {},
diffBuilder = jasmineUnderTest.DiffBuilder({ diffBuilder = new jasmineUnderTest.DiffBuilder({
prettyPrinter: prettyPrinter prettyPrinter: prettyPrinter
}); });
prettyPrinter.customFormat_ = function() {}; prettyPrinter.customFormat_ = function() {};

View File

@@ -104,7 +104,9 @@ describe('toBeInstanceOf', function() {
}); });
it('passes for an async function', function() { it('passes for an async function', function() {
const fn = eval("(async function fn() { return 'foo'; })"); async function fn() {
return 'foo';
}
const matcher = jasmineUnderTest.matchers.toBeInstanceOf(); const matcher = jasmineUnderTest.matchers.toBeInstanceOf();
const result = matcher.compare(fn, Function); const result = matcher.compare(fn, Function);

View File

@@ -24,11 +24,10 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
) { ) {
var f; var f;
if (typeof funcToCall === 'string') { if (typeof funcToCall === 'string') {
/* jshint evil: true */
f = function() { f = function() {
// eslint-disable-next-line no-eval
return eval(funcToCall); return eval(funcToCall);
}; };
/* jshint evil: false */
} else { } else {
f = funcToCall; f = funcToCall;
} }

View File

@@ -329,7 +329,7 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
var expectationFactory = function(actual, spec) { const expectationFactory = function(actual, spec) {
return j$.Expectation.factory({ return j$.Expectation.factory({
matchersUtil: makeMatchersUtil(), matchersUtil: makeMatchersUtil(),
customMatchers: runnableResources[spec.id].customMatchers, customMatchers: runnableResources[spec.id].customMatchers,
@@ -342,16 +342,21 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
// TODO: Unify recordLateError with recordLateExpectation? The extra
// diagnostic info added by the latter is probably useful in most cases.
function recordLateError(error) { function recordLateError(error) {
const result = expectationResultFactory({ const isExpectationResult =
error, error.matcherName !== undefined && error.passed !== undefined;
passed: false, const result = isExpectationResult
matcherName: '', ? error
expected: '', : j$.buildExpectationResult({
actual: '' error,
}); passed: false,
result.globalErrorType = 'lateError'; matcherName: '',
topSuite.result.failedExpectations.push(result); expected: '',
actual: ''
});
routeLateFailure(result);
} }
function recordLateExpectation(runable, runableType, result) { function recordLateExpectation(runable, runableType, result) {
@@ -382,7 +387,27 @@ getJasmineRequireObj().Env = function(j$) {
topSuite.result.failedExpectations.push(delayedExpectationResult); topSuite.result.failedExpectations.push(delayedExpectationResult);
} }
var asyncExpectationFactory = function(actual, spec, runableType) { function routeLateFailure(expectationResult) {
// Report the result on the nearest ancestor suite that hasn't already
// been reported done.
for (let r = currentRunnable(); r; r = r.parentSuite) {
if (!r.reportedDone) {
if (r === topSuite) {
expectationResult.globalErrorType = 'lateError';
}
r.result.failedExpectations.push(expectationResult);
return;
}
}
// If we get here, all results have been reported and there's nothing we
// can do except log the result and hope the user sees it.
console.error('Jasmine received a result after the suite finished:');
console.error(expectationResult);
}
const asyncExpectationFactory = function(actual, spec, runableType) {
return j$.Expectation.asyncFactory({ return j$.Expectation.asyncFactory({
matchersUtil: makeMatchersUtil(), matchersUtil: makeMatchersUtil(),
customAsyncMatchers: runnableResources[spec.id].customAsyncMatchers, customAsyncMatchers: runnableResources[spec.id].customAsyncMatchers,
@@ -397,11 +422,11 @@ getJasmineRequireObj().Env = function(j$) {
return spec.addExpectationResult(passed, result); return spec.addExpectationResult(passed, result);
} }
}; };
var suiteAsyncExpectationFactory = function(actual, suite) { const suiteAsyncExpectationFactory = function(actual, suite) {
return asyncExpectationFactory(actual, suite, 'Suite'); return asyncExpectationFactory(actual, suite, 'Suite');
}; };
var specAsyncExpectationFactory = function(actual, suite) { const specAsyncExpectationFactory = function(actual, suite) {
return asyncExpectationFactory(actual, suite, 'Spec'); return asyncExpectationFactory(actual, suite, 'Spec');
}; };
@@ -474,16 +499,6 @@ getJasmineRequireObj().Env = function(j$) {
return fullName.join(' '); return fullName.join(' ');
}; };
// TODO: we may just be able to pass in the fn instead of wrapping here
var buildExpectationResult = j$.buildExpectationResult,
exceptionFormatter = new j$.ExceptionFormatter(),
expectationResultFactory = function(attrs) {
attrs.messageFormatter = exceptionFormatter.message;
attrs.stackFormatter = exceptionFormatter.stack;
return buildExpectationResult(attrs);
};
/** /**
* Causes a deprecation warning to be logged to the console and reported to * Causes a deprecation warning to be logged to the console and reported to
* reporters. * reporters.
@@ -537,7 +552,7 @@ getJasmineRequireObj().Env = function(j$) {
options.onException = options.onException =
options.onException || options.onException ||
function(e) { function(e) {
(currentRunnable() || topSuite).onException(e); (currentRunnable() || topSuite).handleException(e);
}; };
options.deprecated = self.deprecated; options.deprecated = self.deprecated;
@@ -549,7 +564,6 @@ getJasmineRequireObj().Env = function(j$) {
description: 'Jasmine__TopLevel__Suite', description: 'Jasmine__TopLevel__Suite',
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
autoCleanClosures: config.autoCleanClosures, autoCleanClosures: config.autoCleanClosures,
onLateError: recordLateError onLateError: recordLateError
}); });
@@ -722,10 +736,10 @@ getJasmineRequireObj().Env = function(j$) {
if (suite.hadBeforeAllFailure) { if (suite.hadBeforeAllFailure) {
reportChildrenOfBeforeAllFailure(suite).then(function() { reportChildrenOfBeforeAllFailure(suite).then(function() {
reporter.suiteDone(result, next); reportSuiteDone(suite, result, next);
}); });
} else { } else {
reporter.suiteDone(result, next); reportSuiteDone(suite, result, next);
} }
}, },
orderChildren: function(node) { orderChildren: function(node) {
@@ -815,6 +829,7 @@ getJasmineRequireObj().Env = function(j$) {
failedExpectations: topSuite.result.failedExpectations, failedExpectations: topSuite.result.failedExpectations,
deprecationWarnings: topSuite.result.deprecationWarnings deprecationWarnings: topSuite.result.deprecationWarnings
}; };
topSuite.reportedDone = true;
reporter.jasmineDone(jasmineDoneInfo, function() { reporter.jasmineDone(jasmineDoneInfo, function() {
done(jasmineDoneInfo); done(jasmineDoneInfo);
}); });
@@ -859,7 +874,7 @@ getJasmineRequireObj().Env = function(j$) {
child.result.status = 'failed'; child.result.status = 'failed';
await new Promise(function(resolve) { await new Promise(function(resolve) {
reporter.specDone(child.result, resolve); reportSpecDone(child, child.result, resolve);
}); });
} }
} }
@@ -1007,7 +1022,6 @@ getJasmineRequireObj().Env = function(j$) {
timer: new j$.Timer(), timer: new j$.Timer(),
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
throwOnExpectationFailure: config.stopSpecOnExpectationFailure, throwOnExpectationFailure: config.stopSpecOnExpectationFailure,
autoCleanClosures: config.autoCleanClosures, autoCleanClosures: config.autoCleanClosures,
onLateError: recordLateError onLateError: recordLateError
@@ -1073,7 +1087,7 @@ getJasmineRequireObj().Env = function(j$) {
} }
if (declarationError) { if (declarationError) {
suite.onException(declarationError); suite.handleException(declarationError);
} }
currentDeclarationSuite = parentSuite; currentDeclarationSuite = parentSuite;
@@ -1116,7 +1130,6 @@ getJasmineRequireObj().Env = function(j$) {
}, },
onStart: specStarted, onStart: specStarted,
description: description, description: description,
expectationResultFactory: expectationResultFactory,
queueRunnerFactory: queueRunnerFactory, queueRunnerFactory: queueRunnerFactory,
userContext: function() { userContext: function() {
return suite.clonedSharedUserContext(); return suite.clonedSharedUserContext();
@@ -1139,7 +1152,7 @@ getJasmineRequireObj().Env = function(j$) {
hasFailures = true; hasFailures = true;
} }
reporter.specDone(result, next); reportSpecDone(spec, result, next);
} }
function specStarted(spec, next) { function specStarted(spec, next) {
@@ -1149,6 +1162,16 @@ getJasmineRequireObj().Env = function(j$) {
} }
}; };
function reportSpecDone(spec, result, next) {
spec.reportedDone = true;
reporter.specDone(result, next);
}
function reportSuiteDone(suite, result, next) {
suite.reportedDone = true;
reporter.suiteDone(result, next);
}
this.it_ = function(description, fn, timeout) { this.it_ = function(description, fn, timeout) {
ensureIsNotNested('it'); ensureIsNotNested('it');
// it() sometimes doesn't have a fn argument, so only check the type if // it() sometimes doesn't have a fn argument, so only check the type if

View File

@@ -1,5 +1,5 @@
getJasmineRequireObj().ExceptionFormatter = function(j$) { getJasmineRequireObj().ExceptionFormatter = function(j$) {
var ignoredProperties = [ const ignoredProperties = [
'name', 'name',
'message', 'message',
'stack', 'stack',
@@ -13,9 +13,10 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
]; ];
function ExceptionFormatter(options) { function ExceptionFormatter(options) {
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile(); const jasmineFile =
(options && options.jasmineFile) || j$.util.jasmineFile();
this.message = function(error) { this.message = function(error) {
var message = ''; let message = '';
if (error.jasmineMessage) { if (error.jasmineMessage) {
message += error.jasmineMessage; message += error.jasmineMessage;
@@ -43,9 +44,9 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
return null; return null;
} }
var stackTrace = new j$.StackTrace(error); const stackTrace = new j$.StackTrace(error);
var lines = filterJasmine(stackTrace); const lines = filterJasmine(stackTrace);
var result = ''; let result = '';
if (stackTrace.message && !omitMessage) { if (stackTrace.message && !omitMessage) {
lines.unshift(stackTrace.message); lines.unshift(stackTrace.message);
@@ -58,9 +59,9 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
}; };
function filterJasmine(stackTrace) { function filterJasmine(stackTrace) {
var result = [], const result = [];
jasmineMarker = const jasmineMarker =
stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>'; stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
stackTrace.frames.forEach(function(frame) { stackTrace.frames.forEach(function(frame) {
if (frame.file !== jasmineFile) { if (frame.file !== jasmineFile) {
@@ -78,10 +79,10 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
return; return;
} }
var result = {}; const result = {};
var empty = true; let empty = true;
for (var prop in error) { for (const prop in error) {
if (j$.util.arrayContains(ignoredProperties, prop)) { if (j$.util.arrayContains(ignoredProperties, prop)) {
continue; continue;
} }

View File

@@ -6,8 +6,8 @@ getJasmineRequireObj().Expectation = function(j$) {
function Expectation(options) { function Expectation(options) {
this.expector = new j$.Expector(options); this.expector = new j$.Expector(options);
var customMatchers = options.customMatchers || {}; const customMatchers = options.customMatchers || {};
for (var matcherName in customMatchers) { for (const matcherName in customMatchers) {
this[matcherName] = wrapSyncCompare( this[matcherName] = wrapSyncCompare(
matcherName, matcherName,
customMatchers[matcherName] customMatchers[matcherName]
@@ -77,8 +77,8 @@ getJasmineRequireObj().Expectation = function(j$) {
function AsyncExpectation(options) { function AsyncExpectation(options) {
this.expector = new j$.Expector(options); this.expector = new j$.Expector(options);
var customAsyncMatchers = options.customAsyncMatchers || {}; const customAsyncMatchers = options.customAsyncMatchers || {};
for (var matcherName in customAsyncMatchers) { for (const matcherName in customAsyncMatchers) {
this[matcherName] = wrapAsyncCompare( this[matcherName] = wrapAsyncCompare(
matcherName, matcherName,
customAsyncMatchers[matcherName] customAsyncMatchers[matcherName]
@@ -134,36 +134,34 @@ getJasmineRequireObj().Expectation = function(j$) {
function wrapSyncCompare(name, matcherFactory) { function wrapSyncCompare(name, matcherFactory) {
return function() { return function() {
var result = this.expector.compare(name, matcherFactory, arguments); const result = this.expector.compare(name, matcherFactory, arguments);
this.expector.processResult(result); this.expector.processResult(result);
}; };
} }
function wrapAsyncCompare(name, matcherFactory) { function wrapAsyncCompare(name, matcherFactory) {
return function() { return function() {
var self = this;
// Capture the call stack here, before we go async, so that it will contain // Capture the call stack here, before we go async, so that it will contain
// frames that are relevant to the user instead of just parts of Jasmine. // frames that are relevant to the user instead of just parts of Jasmine.
var errorForStack = j$.util.errorWithStack(); const errorForStack = j$.util.errorWithStack();
return this.expector return this.expector
.compare(name, matcherFactory, arguments) .compare(name, matcherFactory, arguments)
.then(function(result) { .then(result => {
self.expector.processResult(result, errorForStack); this.expector.processResult(result, errorForStack);
}); });
}; };
} }
function addCoreMatchers(prototype, matchers, wrapper) { function addCoreMatchers(prototype, matchers, wrapper) {
for (var matcherName in matchers) { for (const matcherName in matchers) {
var matcher = matchers[matcherName]; const matcher = matchers[matcherName];
prototype[matcherName] = wrapper(matcherName, matcher); prototype[matcherName] = wrapper(matcherName, matcher);
} }
} }
function addFilter(source, filter) { function addFilter(source, filter) {
var result = Object.create(source); const result = Object.create(source);
result.expector = source.expector.addFilter(filter); result.expector = source.expector.addFilter(filter);
return result; return result;
} }
@@ -188,7 +186,7 @@ getJasmineRequireObj().Expectation = function(j$) {
return result; return result;
} }
var syncNegatingFilter = { const syncNegatingFilter = {
selectComparisonFunc: function(matcher) { selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() { function defaultNegativeCompare() {
return negate(matcher.compare.apply(null, arguments)); return negate(matcher.compare.apply(null, arguments));
@@ -199,7 +197,7 @@ getJasmineRequireObj().Expectation = function(j$) {
buildFailureMessage: negatedFailureMessage buildFailureMessage: negatedFailureMessage
}; };
var asyncNegatingFilter = { const asyncNegatingFilter = {
selectComparisonFunc: function(matcher) { selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() { function defaultNegativeCompare() {
return matcher.compare.apply(this, arguments).then(negate); return matcher.compare.apply(this, arguments).then(negate);
@@ -210,10 +208,10 @@ getJasmineRequireObj().Expectation = function(j$) {
buildFailureMessage: negatedFailureMessage buildFailureMessage: negatedFailureMessage
}; };
var expectSettledPromiseFilter = { const expectSettledPromiseFilter = {
selectComparisonFunc: function(matcher) { selectComparisonFunc: function(matcher) {
return function(actual) { return function(actual) {
var matcherArgs = arguments; const matcherArgs = arguments;
return j$.isPending_(actual).then(function(isPending) { return j$.isPending_(actual).then(function(isPending) {
if (isPending) { if (isPending) {
@@ -236,9 +234,7 @@ getJasmineRequireObj().Expectation = function(j$) {
} }
ContextAddingFilter.prototype.modifyFailureMessage = function(msg) { ContextAddingFilter.prototype.modifyFailureMessage = function(msg) {
var nl = msg.indexOf('\n'); if (msg.indexOf('\n') === -1) {
if (nl === -1) {
return this.message + ': ' + msg; return this.message + ': ' + msg;
} else { } else {
return this.message + ':\n' + indent(msg); return this.message + ':\n' + indent(msg);

View File

@@ -1,5 +1,3 @@
/*jshint bitwise: false*/
getJasmineRequireObj().Order = function() { getJasmineRequireObj().Order = function() {
function Order(options) { function Order(options) {
this.random = 'random' in options ? options.random : true; this.random = 'random' in options ? options.random : true;

View File

@@ -1,11 +1,298 @@
getJasmineRequireObj().makePrettyPrinter = function(j$) { getJasmineRequireObj().makePrettyPrinter = function(j$) {
function SinglePrettyPrintRun(customObjectFormatters, pp) { class SinglePrettyPrintRun {
this.customObjectFormatters_ = customObjectFormatters; constructor(customObjectFormatters, pp) {
this.ppNestLevel_ = 0; this.customObjectFormatters_ = customObjectFormatters;
this.seen = []; this.ppNestLevel_ = 0;
this.length = 0; this.seen = [];
this.stringParts = []; this.length = 0;
this.pp_ = pp; this.stringParts = [];
this.pp_ = pp;
}
format(value) {
this.ppNestLevel_++;
try {
const customFormatResult = this.applyCustomFormatters_(value);
if (customFormatResult) {
this.emitScalar(customFormatResult);
} else if (j$.util.isUndefined(value)) {
this.emitScalar('undefined');
} else if (value === null) {
this.emitScalar('null');
} else if (value === 0 && 1 / value === -Infinity) {
this.emitScalar('-0');
} else if (value === j$.getGlobal()) {
this.emitScalar('<global>');
} else if (value.jasmineToString) {
this.emitScalar(value.jasmineToString(this.pp_));
} else if (j$.isString_(value)) {
this.emitString(value);
} else if (j$.isSpy(value)) {
this.emitScalar('spy on ' + value.and.identity);
} else if (j$.isSpy(value.toString)) {
this.emitScalar('spy on ' + value.toString.and.identity);
} else if (value instanceof RegExp) {
this.emitScalar(value.toString());
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (j$.isDomNode(value)) {
if (value.tagName) {
this.emitDomElement(value);
} else {
this.emitScalar('HTMLNode');
}
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (j$.isSet(value)) {
this.emitSet(value);
} else if (j$.isMap(value)) {
this.emitMap(value);
} else if (j$.isTypedArray_(value)) {
this.emitTypedArray(value);
} else if (
value.toString &&
typeof value === 'object' &&
!j$.isArray_(value) &&
hasCustomToString(value)
) {
try {
this.emitScalar(value.toString());
} catch (e) {
this.emitScalar('has-invalid-toString-method');
}
} else if (j$.util.arrayContains(this.seen, value)) {
this.emitScalar(
'<circular reference: ' +
(j$.isArray_(value) ? 'Array' : 'Object') +
'>'
);
} else if (j$.isArray_(value) || j$.isA_('Object', value)) {
this.seen.push(value);
if (j$.isArray_(value)) {
this.emitArray(value);
} else {
this.emitObject(value);
}
this.seen.pop();
} else {
this.emitScalar(value.toString());
}
} catch (e) {
if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) {
throw e;
}
} finally {
this.ppNestLevel_--;
}
}
applyCustomFormatters_(value) {
return customFormat(value, this.customObjectFormatters_);
}
iterateObject(obj, fn) {
const objKeys = j$.MatchersUtil.keys(obj, j$.isArray_(obj));
const length = Math.min(objKeys.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
for (let i = 0; i < length; i++) {
fn(objKeys[i]);
}
return objKeys.length > length;
}
emitScalar(value) {
this.append(value);
}
emitString(value) {
this.append("'" + value + "'");
}
emitArray(array) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Array');
return;
}
const length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
this.append('[ ');
for (let i = 0; i < length; i++) {
if (i > 0) {
this.append(', ');
}
this.format(array[i]);
}
if (array.length > length) {
this.append(', ...');
}
let first = array.length === 0;
const wasTruncated = this.iterateObject(array, property => {
if (first) {
first = false;
} else {
this.append(', ');
}
this.formatProperty(array, property);
});
if (wasTruncated) {
this.append(', ...');
}
this.append(' ]');
}
emitSet(set) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Set');
return;
}
this.append('Set( ');
const size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
let i = 0;
set.forEach(function(value, key) {
if (i >= size) {
return;
}
if (i > 0) {
this.append(', ');
}
this.format(value);
i++;
}, this);
if (set.size > size) {
this.append(', ...');
}
this.append(' )');
}
emitMap(map) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Map');
return;
}
this.append('Map( ');
const size = Math.min(map.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
let i = 0;
map.forEach(function(value, key) {
if (i >= size) {
return;
}
if (i > 0) {
this.append(', ');
}
this.format([key, value]);
i++;
}, this);
if (map.size > size) {
this.append(', ...');
}
this.append(' )');
}
emitObject(obj) {
const ctor = obj.constructor;
const constructorName =
typeof ctor === 'function' && obj instanceof ctor
? j$.fnNameFor(obj.constructor)
: 'null';
this.append(constructorName);
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
return;
}
this.append('({ ');
let first = true;
const wasTruncated = this.iterateObject(obj, property => {
if (first) {
first = false;
} else {
this.append(', ');
}
this.formatProperty(obj, property);
});
if (wasTruncated) {
this.append(', ...');
}
this.append(' })');
}
emitTypedArray(arr) {
const constructorName = j$.fnNameFor(arr.constructor);
const limitedArray = Array.prototype.slice.call(
arr,
0,
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH
);
let itemsString = Array.prototype.join.call(limitedArray, ', ');
if (limitedArray.length !== arr.length) {
itemsString += ', ...';
}
this.append(constructorName + ' [ ' + itemsString + ' ]');
}
emitDomElement(el) {
const tagName = el.tagName.toLowerCase();
let out = '<' + tagName;
for (const attr of el.attributes) {
out += ' ' + attr.name;
if (attr.value !== '') {
out += '="' + attr.value + '"';
}
}
out += '>';
if (el.childElementCount !== 0 || el.textContent !== '') {
out += '...</' + tagName + '>';
}
this.append(out);
}
formatProperty(obj, property) {
if (typeof property === 'symbol') {
this.append(property.toString());
} else {
this.append(property);
}
this.append(': ');
this.format(obj[property]);
}
append(value) {
// This check protects us from the rare case where an object has overriden
// `toString()` with an invalid implementation (returning a non-string).
if (typeof value !== 'string') {
value = Object.prototype.toString.call(value);
}
const result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
this.length += result.value.length;
this.stringParts.push(result.value);
if (result.truncated) {
throw new MaxCharsReachedError();
}
}
} }
function hasCustomToString(value) { function hasCustomToString(value) {
@@ -23,315 +310,6 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
} }
} }
SinglePrettyPrintRun.prototype.format = function(value) {
this.ppNestLevel_++;
try {
var customFormatResult = this.applyCustomFormatters_(value);
if (customFormatResult) {
this.emitScalar(customFormatResult);
} else if (j$.util.isUndefined(value)) {
this.emitScalar('undefined');
} else if (value === null) {
this.emitScalar('null');
} else if (value === 0 && 1 / value === -Infinity) {
this.emitScalar('-0');
} else if (value === j$.getGlobal()) {
this.emitScalar('<global>');
} else if (value.jasmineToString) {
this.emitScalar(value.jasmineToString(this.pp_));
} else if (j$.isString_(value)) {
this.emitString(value);
} else if (j$.isSpy(value)) {
this.emitScalar('spy on ' + value.and.identity);
} else if (j$.isSpy(value.toString)) {
this.emitScalar('spy on ' + value.toString.and.identity);
} else if (value instanceof RegExp) {
this.emitScalar(value.toString());
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (j$.isDomNode(value)) {
if (value.tagName) {
this.emitDomElement(value);
} else {
this.emitScalar('HTMLNode');
}
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (j$.isSet(value)) {
this.emitSet(value);
} else if (j$.isMap(value)) {
this.emitMap(value);
} else if (j$.isTypedArray_(value)) {
this.emitTypedArray(value);
} else if (
value.toString &&
typeof value === 'object' &&
!j$.isArray_(value) &&
hasCustomToString(value)
) {
try {
this.emitScalar(value.toString());
} catch (e) {
this.emitScalar('has-invalid-toString-method');
}
} else if (j$.util.arrayContains(this.seen, value)) {
this.emitScalar(
'<circular reference: ' +
(j$.isArray_(value) ? 'Array' : 'Object') +
'>'
);
} else if (j$.isArray_(value) || j$.isA_('Object', value)) {
this.seen.push(value);
if (j$.isArray_(value)) {
this.emitArray(value);
} else {
this.emitObject(value);
}
this.seen.pop();
} else {
this.emitScalar(value.toString());
}
} catch (e) {
if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) {
throw e;
}
} finally {
this.ppNestLevel_--;
}
};
SinglePrettyPrintRun.prototype.applyCustomFormatters_ = function(value) {
return customFormat(value, this.customObjectFormatters_);
};
SinglePrettyPrintRun.prototype.iterateObject = function(obj, fn) {
var objKeys = j$.MatchersUtil.keys(obj, j$.isArray_(obj));
var isGetter = function isGetter(prop) {};
if (obj.__lookupGetter__) {
isGetter = function isGetter(prop) {
var getter = obj.__lookupGetter__(prop);
return !j$.util.isUndefined(getter) && getter !== null;
};
}
var length = Math.min(objKeys.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
for (var i = 0; i < length; i++) {
var property = objKeys[i];
fn(property, isGetter(property));
}
return objKeys.length > length;
};
SinglePrettyPrintRun.prototype.emitScalar = function(value) {
this.append(value);
};
SinglePrettyPrintRun.prototype.emitString = function(value) {
this.append("'" + value + "'");
};
SinglePrettyPrintRun.prototype.emitArray = function(array) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Array');
return;
}
var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
this.append('[ ');
for (var i = 0; i < length; i++) {
if (i > 0) {
this.append(', ');
}
this.format(array[i]);
}
if (array.length > length) {
this.append(', ...');
}
var self = this;
var first = array.length === 0;
var truncated = this.iterateObject(array, function(property, isGetter) {
if (first) {
first = false;
} else {
self.append(', ');
}
self.formatProperty(array, property, isGetter);
});
if (truncated) {
this.append(', ...');
}
this.append(' ]');
};
SinglePrettyPrintRun.prototype.emitSet = function(set) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Set');
return;
}
this.append('Set( ');
var size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
var i = 0;
set.forEach(function(value, key) {
if (i >= size) {
return;
}
if (i > 0) {
this.append(', ');
}
this.format(value);
i++;
}, this);
if (set.size > size) {
this.append(', ...');
}
this.append(' )');
};
SinglePrettyPrintRun.prototype.emitMap = function(map) {
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Map');
return;
}
this.append('Map( ');
var size = Math.min(map.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
var i = 0;
map.forEach(function(value, key) {
if (i >= size) {
return;
}
if (i > 0) {
this.append(', ');
}
this.format([key, value]);
i++;
}, this);
if (map.size > size) {
this.append(', ...');
}
this.append(' )');
};
SinglePrettyPrintRun.prototype.emitObject = function(obj) {
var ctor = obj.constructor,
constructorName;
constructorName =
typeof ctor === 'function' && obj instanceof ctor
? j$.fnNameFor(obj.constructor)
: 'null';
this.append(constructorName);
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
return;
}
var self = this;
this.append('({ ');
var first = true;
var truncated = this.iterateObject(obj, function(property, isGetter) {
if (first) {
first = false;
} else {
self.append(', ');
}
self.formatProperty(obj, property, isGetter);
});
if (truncated) {
this.append(', ...');
}
this.append(' })');
};
SinglePrettyPrintRun.prototype.emitTypedArray = function(arr) {
var constructorName = j$.fnNameFor(arr.constructor),
limitedArray = Array.prototype.slice.call(
arr,
0,
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH
),
itemsString = Array.prototype.join.call(limitedArray, ', ');
if (limitedArray.length !== arr.length) {
itemsString += ', ...';
}
this.append(constructorName + ' [ ' + itemsString + ' ]');
};
SinglePrettyPrintRun.prototype.emitDomElement = function(el) {
var tagName = el.tagName.toLowerCase(),
attrs = el.attributes,
i,
len = attrs.length,
out = '<' + tagName,
attr;
for (i = 0; i < len; i++) {
attr = attrs[i];
out += ' ' + attr.name;
if (attr.value !== '') {
out += '="' + attr.value + '"';
}
}
out += '>';
if (el.childElementCount !== 0 || el.textContent !== '') {
out += '...</' + tagName + '>';
}
this.append(out);
};
SinglePrettyPrintRun.prototype.formatProperty = function(
obj,
property,
isGetter
) {
if (typeof property === 'symbol') {
this.append(property.toString());
} else {
this.append(property);
}
this.append(': ');
if (isGetter) {
this.append('<getter>');
} else {
this.format(obj[property]);
}
};
SinglePrettyPrintRun.prototype.append = function(value) {
// This check protects us from the rare case where an object has overriden
// `toString()` with an invalid implementation (returning a non-string).
if (typeof value !== 'string') {
value = Object.prototype.toString.call(value);
}
var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
this.length += result.value.length;
this.stringParts.push(result.value);
if (result.truncated) {
throw new MaxCharsReachedError();
}
};
function truncate(s, maxlen) { function truncate(s, maxlen) {
if (s.length <= maxlen) { if (s.length <= maxlen) {
return { value: s, truncated: false }; return { value: s, truncated: false };
@@ -351,10 +329,8 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
MaxCharsReachedError.prototype = new Error(); MaxCharsReachedError.prototype = new Error();
function customFormat(value, customObjectFormatters) { function customFormat(value, customObjectFormatters) {
var i, result; for (const formatter of customObjectFormatters) {
const result = formatter(value);
for (i = 0; i < customObjectFormatters.length; i++) {
result = customObjectFormatters[i](value);
if (result !== undefined) { if (result !== undefined) {
return result; return result;
@@ -365,8 +341,11 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
return function(customObjectFormatters) { return function(customObjectFormatters) {
customObjectFormatters = customObjectFormatters || []; customObjectFormatters = customObjectFormatters || [];
var pp = function(value) { const pp = function(value) {
var prettyPrinter = new SinglePrettyPrintRun(customObjectFormatters, pp); const prettyPrinter = new SinglePrettyPrintRun(
customObjectFormatters,
pp
);
prettyPrinter.format(value); prettyPrinter.format(value);
return prettyPrinter.stringParts.join(''); return prettyPrinter.stringParts.join('');
}; };

View File

@@ -253,8 +253,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
}; };
QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) { QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) {
var msg;
if (retval && j$.isFunction_(retval.then)) { if (retval && j$.isFunction_(retval.then)) {
// Issue a warning that matches the user's code. // Issue a warning that matches the user's code.
// Omit the stack trace because there's almost certainly no user code // Omit the stack trace because there's almost certainly no user code
@@ -274,8 +272,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
'function to not return a promise.' 'function to not return a promise.'
); );
} }
this.deprecated(msg, { omitStackTrace: true });
} }
}; };

View File

@@ -1,28 +1,9 @@
getJasmineRequireObj().Spec = function(j$) { getJasmineRequireObj().Spec = function(j$) {
/**
* @interface Spec
* @see Configuration#specFilter
* @since 2.0.0
*/
function Spec(attrs) { function Spec(attrs) {
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory; this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
/**
* The unique ID of this spec.
* @name Spec#id
* @readonly
* @type {string}
* @since 2.0.0
*/
this.id = attrs.id; this.id = attrs.id;
/**
* The description passed to the {@link it} that created this spec.
* @name Spec#description
* @readonly
* @type {string}
* @since 2.0.0
*/
this.description = attrs.description || ''; this.description = attrs.description || '';
this.queueableFn = attrs.queueableFn; this.queueableFn = attrs.queueableFn;
this.beforeAndAfterFns = this.beforeAndAfterFns =
@@ -43,8 +24,6 @@ getJasmineRequireObj().Spec = function(j$) {
function() { function() {
return ''; return '';
}; };
this.expectationResultFactory =
attrs.expectationResultFactory || function() {};
this.onLateError = attrs.onLateError || function() {}; this.onLateError = attrs.onLateError || function() {};
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = this.catchingExceptions =
@@ -86,14 +65,20 @@ getJasmineRequireObj().Spec = function(j$) {
properties: null, properties: null,
debugLogs: null debugLogs: null
}; };
this.reportedDone = false;
} }
Spec.prototype.addExpectationResult = function(passed, data, isError) { Spec.prototype.addExpectationResult = function(passed, data, isError) {
var expectationResult = this.expectationResultFactory(data); const expectationResult = j$.buildExpectationResult(data);
if (passed) { if (passed) {
this.result.passedExpectations.push(expectationResult); this.result.passedExpectations.push(expectationResult);
} else { } else {
this.result.failedExpectations.push(expectationResult); if (this.reportedDone) {
this.onLateError(expectationResult);
} else {
this.result.failedExpectations.push(expectationResult);
}
if (this.throwOnExpectationFailure && !isError) { if (this.throwOnExpectationFailure && !isError) {
throw new j$.errors.ExpectationFailed(); throw new j$.errors.ExpectationFailed();
@@ -147,7 +132,7 @@ getJasmineRequireObj().Spec = function(j$) {
isLeaf: true, isLeaf: true,
queueableFns: [...fns.befores, this.queueableFn, ...fns.afters], queueableFns: [...fns.befores, this.queueableFn, ...fns.afters],
onException: function() { onException: function() {
self.onException.apply(self, arguments); self.handleException.apply(self, arguments);
}, },
onMultipleDone: function() { onMultipleDone: function() {
// Issue a deprecation. Include the context ourselves and pass // Issue a deprecation. Include the context ourselves and pass
@@ -197,9 +182,10 @@ getJasmineRequireObj().Spec = function(j$) {
debugLogs: null debugLogs: null
}; };
this.markedPending = this.markedExcluding; this.markedPending = this.markedExcluding;
this.reportedDone = false;
}; };
Spec.prototype.onException = function onException(e) { Spec.prototype.handleException = function handleException(e) {
if (Spec.isPendingSpecException(e)) { if (Spec.isPendingSpecException(e)) {
this.pend(extractCustomPendingMessage(e)); this.pend(extractCustomPendingMessage(e));
return; return;
@@ -273,13 +259,6 @@ getJasmineRequireObj().Spec = function(j$) {
return 'passed'; return 'passed';
}; };
/**
* The full description including all ancestors of this spec.
* @name Spec#getFullName
* @function
* @returns {string}
* @since 2.0.0
*/
Spec.prototype.getFullName = function() { Spec.prototype.getFullName = function() {
return this.getSpecName(this); return this.getSpecName(this);
}; };
@@ -289,7 +268,7 @@ getJasmineRequireObj().Spec = function(j$) {
deprecation = { message: deprecation }; deprecation = { message: deprecation };
} }
this.result.deprecationWarnings.push( this.result.deprecationWarnings.push(
this.expectationResultFactory(deprecation) j$.buildExpectationResult(deprecation)
); );
}; };
@@ -332,6 +311,7 @@ getJasmineRequireObj().Spec = function(j$) {
/** /**
* @interface Spec * @interface Spec
* @see Configuration#specFilter * @see Configuration#specFilter
* @since 2.0.0
*/ */
Object.defineProperty(Spec.prototype, 'metadata', { Object.defineProperty(Spec.prototype, 'metadata', {
get: function() { get: function() {
@@ -342,6 +322,7 @@ getJasmineRequireObj().Spec = function(j$) {
* @name Spec#id * @name Spec#id
* @readonly * @readonly
* @type {string} * @type {string}
* @since 2.0.0
*/ */
id: this.id, id: this.id,
@@ -350,6 +331,7 @@ getJasmineRequireObj().Spec = function(j$) {
* @name Spec#description * @name Spec#description
* @readonly * @readonly
* @type {string} * @type {string}
* @since 2.0.0
*/ */
description: this.description, description: this.description,
@@ -358,6 +340,7 @@ getJasmineRequireObj().Spec = function(j$) {
* @name Spec#getFullName * @name Spec#getFullName
* @function * @function
* @returns {string} * @returns {string}
* @since 2.0.0
*/ */
getFullName: this.getFullName.bind(this) getFullName: this.getFullName.bind(this)
}; };

View File

@@ -1,48 +1,21 @@
getJasmineRequireObj().Suite = function(j$) { getJasmineRequireObj().Suite = function(j$) {
/**
* @interface Suite
* @see Env#topSuite
* @since 2.0.0
*/
function Suite(attrs) { function Suite(attrs) {
this.env = attrs.env; this.env = attrs.env;
/**
* The unique ID of this suite.
* @name Suite#id
* @readonly
* @type {string}
* @since 2.0.0
*/
this.id = attrs.id; this.id = attrs.id;
this.parentSuite = attrs.parentSuite; this.parentSuite = attrs.parentSuite;
/**
* The description passed to the {@link describe} that created this suite.
* @name Suite#description
* @readonly
* @type {string}
* @since 2.0.0
*/
this.description = attrs.description; this.description = attrs.description;
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory; this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.autoCleanClosures = this.autoCleanClosures =
attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures; attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
this.onLateError = attrs.onLateError; this.onLateError = attrs.onLateError || function() {};
this.beforeFns = []; this.beforeFns = [];
this.afterFns = []; this.afterFns = [];
this.beforeAllFns = []; this.beforeAllFns = [];
this.afterAllFns = []; this.afterAllFns = [];
this.timer = attrs.timer || new j$.Timer(); this.timer = attrs.timer || new j$.Timer();
/**
* The suite's children.
* @name Suite#children
* @type {Array.<(Spec|Suite)>}
* @since 2.0.0
*/
this.children = []; this.children = [];
this.reset(); this.reset();
@@ -61,13 +34,6 @@ getJasmineRequireObj().Suite = function(j$) {
return this.asyncExpectationFactory(actual, this); return this.asyncExpectationFactory(actual, this);
}; };
/**
* The full description including all ancestors of this suite.
* @name Suite#getFullName
* @function
* @returns {string}
* @since 2.0.0
*/
Suite.prototype.getFullName = function() { Suite.prototype.getFullName = function() {
var fullName = []; var fullName = [];
for ( for (
@@ -163,6 +129,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.children.forEach(function(child) { this.children.forEach(function(child) {
child.reset(); child.reset();
}); });
this.reportedDone = false;
}; };
Suite.prototype.addChild = function(child) { Suite.prototype.addChild = function(child) {
@@ -204,25 +171,29 @@ getJasmineRequireObj().Suite = function(j$) {
return j$.UserContext.fromExisting(this.sharedUserContext()); return j$.UserContext.fromExisting(this.sharedUserContext());
}; };
Suite.prototype.onException = function() { Suite.prototype.handleException = function() {
if (arguments[0] instanceof j$.errors.ExpectationFailed) { if (arguments[0] instanceof j$.errors.ExpectationFailed) {
return; return;
} }
var data = { const data = {
matcherName: '', matcherName: '',
passed: false, passed: false,
expected: '', expected: '',
actual: '', actual: '',
error: arguments[0] error: arguments[0]
}; };
var failedExpectation = this.expectationResultFactory(data); const failedExpectation = j$.buildExpectationResult(data);
if (!this.parentSuite) { if (!this.parentSuite) {
failedExpectation.globalErrorType = 'afterAll'; failedExpectation.globalErrorType = 'afterAll';
} }
this.result.failedExpectations.push(failedExpectation); if (this.reportedDone) {
this.onLateError(failedExpectation);
} else {
this.result.failedExpectations.push(failedExpectation);
}
}; };
Suite.prototype.onMultipleDone = function() { Suite.prototype.onMultipleDone = function() {
@@ -249,8 +220,15 @@ getJasmineRequireObj().Suite = function(j$) {
Suite.prototype.addExpectationResult = function() { Suite.prototype.addExpectationResult = function() {
if (isFailure(arguments)) { if (isFailure(arguments)) {
var data = arguments[1]; const data = arguments[1];
this.result.failedExpectations.push(this.expectationResultFactory(data)); const expectationResult = j$.buildExpectationResult(data);
if (this.reportedDone) {
this.onLateError(expectationResult);
} else {
this.result.failedExpectations.push(expectationResult);
}
if (this.throwOnExpectationFailure) { if (this.throwOnExpectationFailure) {
throw new j$.errors.ExpectationFailed(); throw new j$.errors.ExpectationFailed();
} }
@@ -262,7 +240,7 @@ getJasmineRequireObj().Suite = function(j$) {
deprecation = { message: deprecation }; deprecation = { message: deprecation };
} }
this.result.deprecationWarnings.push( this.result.deprecationWarnings.push(
this.expectationResultFactory(deprecation) j$.buildExpectationResult(deprecation)
); );
}; };
@@ -279,6 +257,7 @@ getJasmineRequireObj().Suite = function(j$) {
/** /**
* @interface Suite * @interface Suite
* @see Env#topSuite * @see Env#topSuite
* @since 2.0.0
*/ */
function SuiteMetadata(suite) { function SuiteMetadata(suite) {
this.suite_ = suite; this.suite_ = suite;
@@ -287,6 +266,7 @@ getJasmineRequireObj().Suite = function(j$) {
* @name Suite#id * @name Suite#id
* @readonly * @readonly
* @type {string} * @type {string}
* @since 2.0.0
*/ */
this.id = suite.id; this.id = suite.id;
@@ -303,6 +283,7 @@ getJasmineRequireObj().Suite = function(j$) {
* @name Suite#description * @name Suite#description
* @readonly * @readonly
* @type {string} * @type {string}
* @since 2.0.0
*/ */
this.description = suite.description; this.description = suite.description;
} }
@@ -312,6 +293,7 @@ getJasmineRequireObj().Suite = function(j$) {
* @name Suite#getFullName * @name Suite#getFullName
* @function * @function
* @returns {string} * @returns {string}
* @since 2.0.0
*/ */
SuiteMetadata.prototype.getFullName = function() { SuiteMetadata.prototype.getFullName = function() {
return this.suite_.getFullName(); return this.suite_.getFullName();
@@ -321,6 +303,7 @@ getJasmineRequireObj().Suite = function(j$) {
* The suite's children. * The suite's children.
* @name Suite#children * @name Suite#children
* @type {Array.<(Spec|Suite)>} * @type {Array.<(Spec|Suite)>}
* @since 2.0.0
*/ */
Object.defineProperty(SuiteMetadata.prototype, 'children', { Object.defineProperty(SuiteMetadata.prototype, 'children', {
get: function() { get: function() {

View File

@@ -42,7 +42,7 @@ getJasmineRequireObj().TreeProcessor = function() {
queueableFns: childFns, queueableFns: childFns,
userContext: tree.sharedUserContext(), userContext: tree.sharedUserContext(),
onException: function() { onException: function() {
tree.onException.apply(tree, arguments); tree.handleException.apply(tree, arguments);
}, },
onComplete: done, onComplete: done,
onMultipleDone: tree.onMultipleDone onMultipleDone: tree.onMultipleDone
@@ -218,7 +218,7 @@ getJasmineRequireObj().TreeProcessor = function() {
queueableFns: [onStart].concat(wrapChildren(node, segmentNumber)), queueableFns: [onStart].concat(wrapChildren(node, segmentNumber)),
userContext: node.sharedUserContext(), userContext: node.sharedUserContext(),
onException: function() { onException: function() {
node.onException.apply(node, arguments); node.handleException.apply(node, arguments);
}, },
onMultipleDone: node.onMultipleDone onMultipleDone: node.onMultipleDone
? node.onMultipleDone.bind(node) ? node.onMultipleDone.bind(node)

View File

@@ -30,12 +30,9 @@ getJasmineRequireObj().Any = function(j$) {
return typeof other == 'boolean'; return typeof other == 'boolean';
} }
/* jshint -W122 */
/* global Symbol */
if (typeof Symbol != 'undefined' && this.expectedObject == Symbol) { if (typeof Symbol != 'undefined' && this.expectedObject == Symbol) {
return typeof other == 'symbol'; return typeof other == 'symbol';
} }
/* jshint +W122 */
return other instanceof this.expectedObject; return other instanceof this.expectedObject;
}; };

View File

@@ -0,0 +1,17 @@
getJasmineRequireObj().Is = function(j$) {
class Is {
constructor(expected) {
this.expected_ = expected;
}
asymmetricMatch(actual) {
return actual === this.expected_;
}
jasmineToString(pp) {
return `<jasmine.is(${pp(this.expected_)})>`;
}
}
return Is;
};

View File

@@ -283,6 +283,18 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
return new j$.Empty(); 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.is
* @function
* @param {Object} sample - The value to compare the actual to.
*/
j$.is = function(sample) {
return new j$.Is(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}), * 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. * that will succeed if the actual value being compared is not empty.

View File

@@ -1,8 +1,7 @@
//TODO: expectation result may make more sense as a presentation of an expectation. //TODO: expectation result may make more sense as a presentation of an expectation.
getJasmineRequireObj().buildExpectationResult = function(j$) { getJasmineRequireObj().buildExpectationResult = function(j$) {
function buildExpectationResult(options) { function buildExpectationResult(options) {
var messageFormatter = options.messageFormatter || function() {}, const exceptionFormatter = new j$.ExceptionFormatter();
stackFormatter = options.stackFormatter || function() {};
/** /**
* @typedef Expectation * @typedef Expectation
@@ -16,7 +15,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
* is reported on the top suite. Valid values are undefined, "afterAll", * is reported on the top suite. Valid values are undefined, "afterAll",
* "load", "lateExpectation", and "lateError". * "load", "lateExpectation", and "lateError".
*/ */
var result = { const result = {
matcherName: options.matcherName, matcherName: options.matcherName,
message: message(), message: message(),
stack: options.omitStackTrace ? '' : stack(), stack: options.omitStackTrace ? '' : stack(),
@@ -52,7 +51,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
} else if (options.message) { } else if (options.message) {
return options.message; return options.message;
} else if (options.error) { } else if (options.error) {
return messageFormatter(options.error); return exceptionFormatter.message(options.error);
} }
return ''; return '';
} }
@@ -62,7 +61,8 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
return ''; return '';
} }
var error = options.error; let error = options.error;
if (!error) { if (!error) {
if (options.errorForStack) { if (options.errorForStack) {
error = options.errorForStack; error = options.errorForStack;
@@ -78,7 +78,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
} }
// Omit the message from the stack trace because it will be // Omit the message from the stack trace because it will be
// included elsewhere. // included elsewhere.
return stackFormatter(error, { omitMessage: true }); return exceptionFormatter.stack(error, { omitMessage: true });
} }
} }

View File

@@ -1,118 +1,112 @@
getJasmineRequireObj().DiffBuilder = function(j$) { getJasmineRequireObj().DiffBuilder = function(j$) {
return function DiffBuilder(config) { class DiffBuilder {
var prettyPrinter = (config || {}).prettyPrinter || j$.makePrettyPrinter(), constructor(config) {
mismatches = new j$.MismatchTree(), this.prettyPrinter_ =
path = new j$.ObjectPath(), (config || {}).prettyPrinter || j$.makePrettyPrinter();
actualRoot = undefined, this.mismatches_ = new j$.MismatchTree();
expectedRoot = undefined; this.path_ = new j$.ObjectPath();
this.actualRoot_ = undefined;
this.expectedRoot_ = undefined;
}
return { setRoots(actual, expected) {
setRoots: function(actual, expected) { this.actualRoot_ = actual;
actualRoot = actual; this.expectedRoot_ = expected;
expectedRoot = expected; }
},
recordMismatch: function(formatter) { recordMismatch(formatter) {
mismatches.add(path, formatter); this.mismatches_.add(this.path_, formatter);
}, }
getMessage: function() { getMessage() {
var messages = []; const messages = [];
mismatches.traverse(function(path, isLeaf, formatter) { this.mismatches_.traverse((path, isLeaf, formatter) => {
var actualCustom, const { actual, expected } = this.dereferencePath_(path);
expectedCustom,
useCustom,
derefResult = dereferencePath(
path,
actualRoot,
expectedRoot,
prettyPrinter
),
actual = derefResult.actual,
expected = derefResult.expected;
if (formatter) {
messages.push(formatter(actual, expected, path, prettyPrinter));
return true;
}
actualCustom = prettyPrinter.customFormat_(actual);
expectedCustom = prettyPrinter.customFormat_(expected);
useCustom = !(
j$.util.isUndefined(actualCustom) &&
j$.util.isUndefined(expectedCustom)
);
if (useCustom) {
messages.push(
wrapPrettyPrinted(actualCustom, expectedCustom, path)
);
return false; // don't recurse further
}
if (isLeaf) {
messages.push(
defaultFormatter(actual, expected, path, prettyPrinter)
);
}
if (formatter) {
messages.push(formatter(actual, expected, path, this.prettyPrinter_));
return true; return true;
}); }
return messages.join('\n'); const actualCustom = this.prettyPrinter_.customFormat_(actual);
}, const expectedCustom = this.prettyPrinter_.customFormat_(expected);
const useCustom = !(
j$.util.isUndefined(actualCustom) &&
j$.util.isUndefined(expectedCustom)
);
withPath: function(pathComponent, block) { if (useCustom) {
var oldPath = path; messages.push(wrapPrettyPrinted(actualCustom, expectedCustom, path));
path = path.add(pathComponent); return false; // don't recurse further
block(); }
path = oldPath;
if (isLeaf) {
messages.push(this.defaultFormatter_(actual, expected, path));
}
return true;
});
return messages.join('\n');
}
withPath(pathComponent, block) {
const oldPath = this.path_;
this.path_ = this.path_.add(pathComponent);
block();
this.path_ = oldPath;
}
dereferencePath_(objectPath) {
let actual = this.actualRoot_;
let expected = this.expectedRoot_;
const handleAsymmetricExpected = () => {
if (
j$.isAsymmetricEqualityTester_(expected) &&
j$.isFunction_(expected.valuesForDiff_)
) {
const asymmetricResult = expected.valuesForDiff_(
actual,
this.prettyPrinter_
);
expected = asymmetricResult.self;
actual = asymmetricResult.other;
}
};
handleAsymmetricExpected();
for (const pc of objectPath.components) {
actual = actual[pc];
expected = expected[pc];
handleAsymmetricExpected();
} }
};
function defaultFormatter(actual, expected, path, prettyPrinter) { return { actual: actual, expected: expected };
}
defaultFormatter_(actual, expected, path) {
return wrapPrettyPrinted( return wrapPrettyPrinted(
prettyPrinter(actual), this.prettyPrinter_(actual),
prettyPrinter(expected), this.prettyPrinter_(expected),
path path
); );
} }
function wrapPrettyPrinted(actual, expected, path) {
return (
'Expected ' +
path +
(path.depth() ? ' = ' : '') +
actual +
' to equal ' +
expected +
'.'
);
}
};
function dereferencePath(objectPath, actual, expected, pp) {
function handleAsymmetricExpected() {
if (
j$.isAsymmetricEqualityTester_(expected) &&
j$.isFunction_(expected.valuesForDiff_)
) {
var asymmetricResult = expected.valuesForDiff_(actual, pp);
expected = asymmetricResult.self;
actual = asymmetricResult.other;
}
}
var i;
handleAsymmetricExpected();
for (i = 0; i < objectPath.components.length; i++) {
actual = actual[objectPath.components[i]];
expected = expected[objectPath.components[i]];
handleAsymmetricExpected();
}
return { actual: actual, expected: expected };
} }
function wrapPrettyPrinted(actual, expected, path) {
return (
'Expected ' +
path +
(path.depth() ? ' = ' : '') +
actual +
' to equal ' +
expected +
'.'
);
}
return DiffBuilder;
}; };

View File

@@ -6,56 +6,51 @@ getJasmineRequireObj().MismatchTree = function(j$) {
the expected and actual object graphs. MismatchTree maintains that context the expected and actual object graphs. MismatchTree maintains that context
and provides it via the traverse method. and provides it via the traverse method.
*/ */
function MismatchTree(path) { class MismatchTree {
this.path = path || new j$.ObjectPath([]); constructor(path) {
this.formatter = undefined; this.path = path || new j$.ObjectPath([]);
this.children = []; this.formatter = undefined;
this.isMismatch = false; this.children = [];
} this.isMismatch = false;
MismatchTree.prototype.add = function(path, formatter) {
var key, child;
if (path.depth() === 0) {
this.formatter = formatter;
this.isMismatch = true;
} else {
key = path.components[0];
path = path.shift();
child = this.child(key);
if (!child) {
child = new MismatchTree(this.path.add(key));
this.children.push(child);
}
child.add(path, formatter);
} }
};
MismatchTree.prototype.traverse = function(visit) { add(path, formatter) {
var i, if (path.depth() === 0) {
hasChildren = this.children.length > 0; this.formatter = formatter;
this.isMismatch = true;
} else {
const key = path.components[0];
path = path.shift();
let child = this.child(key);
if (this.isMismatch || hasChildren) { if (!child) {
if (visit(this.path, !hasChildren, this.formatter)) { child = new MismatchTree(this.path.add(key));
for (i = 0; i < this.children.length; i++) { this.children.push(child);
this.children[i].traverse(visit); }
child.add(path, formatter);
}
}
traverse(visit) {
const hasChildren = this.children.length > 0;
if (this.isMismatch || hasChildren) {
if (visit(this.path, !hasChildren, this.formatter)) {
for (const child of this.children) {
child.traverse(visit);
}
} }
} }
} }
};
MismatchTree.prototype.child = function(key) { child(key) {
var i, pathEls; return this.children.find(child => {
const pathEls = child.path.components;
for (i = 0; i < this.children.length; i++) { return pathEls[pathEls.length - 1] === key;
pathEls = this.children[i].path.components; });
if (pathEls[pathEls.length - 1] === key) {
return this.children[i];
}
} }
}; }
return MismatchTree; return MismatchTree;
}; };

View File

@@ -1,27 +1,29 @@
getJasmineRequireObj().ObjectPath = function(j$) { getJasmineRequireObj().ObjectPath = function(j$) {
function ObjectPath(components) { class ObjectPath {
this.components = components || []; constructor(components) {
} this.components = components || [];
ObjectPath.prototype.toString = function() {
if (this.components.length) {
return '$' + map(this.components, formatPropertyAccess).join('');
} else {
return '';
} }
};
ObjectPath.prototype.add = function(component) { toString() {
return new ObjectPath(this.components.concat([component])); if (this.components.length) {
}; return '$' + this.components.map(formatPropertyAccess).join('');
} else {
return '';
}
}
ObjectPath.prototype.shift = function() { add(component) {
return new ObjectPath(this.components.slice(1)); return new ObjectPath(this.components.concat([component]));
}; }
ObjectPath.prototype.depth = function() { shift() {
return this.components.length; return new ObjectPath(this.components.slice(1));
}; }
depth() {
return this.components.length;
}
}
function formatPropertyAccess(prop) { function formatPropertyAccess(prop) {
if (typeof prop === 'number' || typeof prop === 'symbol') { if (typeof prop === 'number' || typeof prop === 'symbol') {
@@ -32,15 +34,7 @@ getJasmineRequireObj().ObjectPath = function(j$) {
return '.' + prop; return '.' + prop;
} }
return "['" + prop + "']"; return `['${prop}']`;
}
function map(array, fn) {
var results = [];
for (var i = 0; i < array.length; i++) {
results.push(fn(array[i]));
}
return results;
} }
function isValidIdentifier(string) { function isValidIdentifier(string) {

View File

@@ -14,7 +14,7 @@ getJasmineRequireObj().toEqual = function(j$) {
var result = { var result = {
pass: false pass: false
}, },
diffBuilder = j$.DiffBuilder({ prettyPrinter: matchersUtil.pp }); diffBuilder = new j$.DiffBuilder({ prettyPrinter: matchersUtil.pp });
result.pass = matchersUtil.equals(actual, expected, diffBuilder); result.pass = matchersUtil.equals(actual, expected, diffBuilder);

View File

@@ -91,6 +91,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.Falsy = jRequire.Falsy(j$); j$.Falsy = jRequire.Falsy(j$);
j$.Empty = jRequire.Empty(j$); j$.Empty = jRequire.Empty(j$);
j$.NotEmpty = jRequire.NotEmpty(j$); j$.NotEmpty = jRequire.NotEmpty(j$);
j$.Is = jRequire.Is(j$);
j$.matchers = jRequire.requireMatchers(jRequire, j$); j$.matchers = jRequire.requireMatchers(jRequire, j$);
j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$); j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);