Merge branch 'main' into 3.99

This commit is contained in:
Steve Gravrock
2021-08-17 17:08:34 -07:00
7 changed files with 418 additions and 184 deletions

View File

@@ -772,4 +772,26 @@ describe('Env', function() {
expect(suiteThis).toBeInstanceOf(jasmineUnderTest.Suite);
});
describe('#execute', function() {
it('returns a promise when the environment supports promises', function() {
jasmine.getEnv().requirePromises();
expect(env.execute()).toBeInstanceOf(Promise);
});
it('returns a promise when a custom promise constructor is provided', function() {
function CustomPromise() {}
CustomPromise.resolve = function() {};
CustomPromise.reject = function() {};
spyOn(env, 'deprecated');
env.configure({ Promise: CustomPromise });
expect(env.execute()).toBeInstanceOf(CustomPromise);
});
it('returns undefined when promises are unavailable', function() {
jasmine.getEnv().requireNoPromises();
expect(env.execute()).toBeUndefined();
});
});
});

View File

@@ -170,84 +170,118 @@ describe('GlobalErrors', function() {
);
});
it('reports unhandled promise rejections in node.js', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: jasmine.createSpy('process.removeListener'),
listeners: jasmine
.createSpy('process.listeners')
.and.returnValue(['foo']),
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
describe('Reporting unhandled promise rejections in node.js', function() {
it('reports rejections with `Error` reasons', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: jasmine.createSpy('process.removeListener'),
listeners: jasmine
.createSpy('process.listeners')
.and.returnValue(['foo']),
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
jasmine.any(Function)
);
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
'unhandledRejection'
);
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
'unhandledRejection'
);
errors.install();
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
jasmine.any(Function)
);
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
'unhandledRejection'
);
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
'unhandledRejection'
);
errors.pushListener(handler);
errors.pushListener(handler);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(new Error('bar'));
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
'Unhandled promise rejection: Error: bar'
);
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
'Unhandled promise rejection: Error: bar'
);
errors.uninstall();
errors.uninstall();
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
'unhandledRejection',
addedListener
);
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
'foo'
);
});
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
'unhandledRejection',
addedListener
);
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
'foo'
);
});
it('reports unhandled promise rejections in node.js when no error is provided', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: function() {},
listeners: function() {
return [];
},
removeAllListeners: function() {}
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
it('reports rejections with non-`Error` reasons', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: function() {},
listeners: function() {
return [];
},
removeAllListeners: function() {}
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
errors.install();
errors.pushListener(handler);
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
'unhandledRejection'
);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(undefined);
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
'unhandledRejection'
);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(17);
expect(handler).toHaveBeenCalledWith(
new Error(
'Unhandled promise rejection with no error or message\n' +
'(Tip: to get a useful stack trace, use ' +
'Promise.reject(new Error(...)) instead of Promise.reject().)'
)
);
expect(handler).toHaveBeenCalledWith(
new Error(
'Unhandled promise rejection: 17\n' +
'(Tip: to get a useful stack trace, use ' +
'Promise.reject(new Error(...)) instead of Promise.reject(...).)'
)
);
});
it('reports rejections with no reason provided', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: function() {},
listeners: function() {
return [];
},
removeAllListeners: function() {}
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
'unhandledRejection'
);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(undefined);
expect(handler).toHaveBeenCalledWith(
new Error(
'Unhandled promise rejection with no error or message\n' +
'(Tip: to get a useful stack trace, use ' +
'Promise.reject(new Error(...)) instead of Promise.reject().)'
)
);
});
});
describe('Reporting unhandled promise rejections in the browser', function() {

View File

@@ -2977,6 +2977,112 @@ describe('Env integration', function() {
env.execute(null, done);
});
describe('The promise returned by #execute', function() {
beforeEach(function() {
this.savedInterval = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
});
afterEach(function() {
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = this.savedInterval;
});
it('is resolved after reporter events are dispatched', function() {
jasmine.getEnv().requirePromises();
var reporter = jasmine.createSpyObj('reporter', [
'specDone',
'suiteDone',
'jasmineDone'
]);
env.addReporter(reporter);
env.describe('suite', function() {
env.it('spec', function() {});
});
return env.execute(null).then(function() {
expect(reporter.specDone).toHaveBeenCalled();
expect(reporter.suiteDone).toHaveBeenCalled();
expect(reporter.jasmineDone).toHaveBeenCalled();
});
});
it('is resolved after the stack is cleared', function(done) {
jasmine.getEnv().requirePromises();
var realClearStack = jasmineUnderTest.getClearStack(
jasmineUnderTest.getGlobal()
),
clearStackSpy = jasmine
.createSpy('clearStack')
.and.callFake(realClearStack);
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(clearStackSpy);
// Create a new env that has the clearStack defined above
env.cleanup_();
env = new jasmineUnderTest.Env();
env.describe('suite', function() {
env.it('spec', function() {});
});
env.execute(null).then(function() {
expect(clearStackSpy).toHaveBeenCalled(); // (many times)
clearStackSpy.calls.reset();
setTimeout(function() {
expect(clearStackSpy).not.toHaveBeenCalled();
done();
});
});
});
it('is resolved after QueueRunner timeouts are cleared', function() {
jasmine.getEnv().requirePromises();
var setTimeoutSpy = spyOn(
jasmineUnderTest.getGlobal(),
'setTimeout'
).and.callThrough();
var clearTimeoutSpy = spyOn(
jasmineUnderTest.getGlobal(),
'clearTimeout'
).and.callThrough();
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 123456; // a distinctive value
env = new jasmineUnderTest.Env();
env.describe('suite', function() {
env.it('spec', function() {});
});
return env.execute(null).then(function() {
var timeoutIds = setTimeoutSpy.calls
.all()
.filter(function(call) {
return call.args[1] === 123456;
})
.map(function(call) {
return call.returnValue;
});
expect(timeoutIds.length).toBeGreaterThan(0);
timeoutIds.forEach(function(timeoutId) {
expect(clearTimeoutSpy).toHaveBeenCalledWith(timeoutId);
});
});
});
it('is resolved even if specs fail', function() {
jasmine.getEnv().requirePromises();
env.describe('suite', function() {
env.it('spec', function() {
env.expect(true).toBe(false);
});
});
return expectAsync(env.execute(null)).toBeResolved();
});
});
describe('The optional callback argument to #execute', function() {
beforeEach(function() {
this.savedInterval = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;