Redesigned moudule system

* Top level private APIs (e.g. jasmine.private.whatever) are no longer
  exposed
* jasmineRequire is no longer exposed
* core is self-booting
* Globals are automatically created in browsers. (They can subsequently
  be removed by user code if desired.)
* Globals are *not* automatically created in Node. An installGlobals
  function is exported instead. The jasmine package calls installGlobals
  unless configured not to do so.
* In Node, the same instance is returned each time jasmine-core is
  imported. A reset function is exported. It effectively resets all state
  by discarding the env and creating a new one. This allows mulitple
  sequential runs within the same process to be independent of each
  other, but does not allow multiple concurrent runs. (That probably never
  worked anyway.)

Fixes #2094
This commit is contained in:
Steve Gravrock
2026-02-15 13:41:19 -08:00
parent 03006080d4
commit f12f4395f0
127 changed files with 1336 additions and 1367 deletions

View File

@@ -173,10 +173,13 @@ describe('ExceptionFormatter', function() {
});
it('filters Jasmine stack frames in this environment', function() {
const jasmineFile = (function() {
const trace = new privateUnderTest.StackTrace(new Error());
return trace.frames[2].file;
})();
expect(jasmineFile).toMatch(/\/jasmine.js$/);
const error = new Error('an error');
const subject = new privateUnderTest.ExceptionFormatter({
jasmineFile: jasmine.private.util.jasmineFile()
});
const subject = new privateUnderTest.ExceptionFormatter({ jasmineFile });
const result = subject.stack(error);
jasmine.debugLog('Original stack trace: ' + error.stack);
jasmine.debugLog('Filtered stack trace: ' + result);
@@ -196,15 +199,18 @@ describe('ExceptionFormatter', function() {
});
it('handles multiline error messages in this environment', function() {
const jasmineFile = (function() {
const trace = new privateUnderTest.StackTrace(new Error());
return trace.frames[2].file;
})();
expect(jasmineFile).toMatch(/\/jasmine.js$/);
const msg = 'an error\nwith two lines';
const error = new Error(msg);
if (error.stack.indexOf(msg) === -1) {
pending("Stack traces don't have messages in this environment");
}
const subject = new privateUnderTest.ExceptionFormatter({
jasmineFile: jasmine.private.util.jasmineFile()
});
const subject = new privateUnderTest.ExceptionFormatter({ jasmineFile });
const result = subject.stack(error);
const lines = result.split('\n');
@@ -284,7 +290,7 @@ describe('ExceptionFormatter', function() {
it('ensures that stack traces do not include the message in this environment', function() {
const error = new Error('an error');
const subject = new privateUnderTest.ExceptionFormatter({
jasmineFile: jasmine.private.util.jasmineFile()
jasmineFile: "doesn't matter"
});
const result = subject.stack(error, { omitMessage: true });
expect(result).not.toContain('an error');

View File

@@ -278,7 +278,7 @@ describe('Spec', function() {
spec.addExpectationResult(true, { message: 'passed' });
expect(function() {
spec.addExpectationResult(false, { message: 'failed' });
}).toThrowError(jasmineUnderTest.private.errors.ExpectationFailed);
}).toThrowError(privateUnderTest.errors.ExpectationFailed);
expect(spec.doneEvent().failedExpectations).toEqual([
jasmine.objectContaining({ message: 'failed' })
@@ -453,9 +453,7 @@ describe('Spec', function() {
queueableFn: {}
});
spec.handleException(
new jasmineUnderTest.private.errors.ExpectationFailed()
);
spec.handleException(new privateUnderTest.errors.ExpectationFailed());
expect(spec.doneEvent().failedExpectations).toEqual([]);
});

View File

@@ -138,7 +138,7 @@ describe('Suite', function() {
expect(function() {
suite.addExpectationResult(false, { message: 'failed' });
}).toThrowError(jasmineUnderTest.private.errors.ExpectationFailed);
}).toThrowError(privateUnderTest.errors.ExpectationFailed);
expect(suite.doneEvent().status).toBe('failed');
expect(suite.doneEvent().failedExpectations).toEqual([
@@ -149,9 +149,7 @@ describe('Suite', function() {
it('does not add an additional failure when an expectation fails', function() {
const suite = new privateUnderTest.Suite({});
suite.handleException(
new jasmineUnderTest.private.errors.ExpectationFailed()
);
suite.handleException(new privateUnderTest.errors.ExpectationFailed());
expect(suite.doneEvent().failedExpectations).toEqual([]);
});

View File

@@ -163,7 +163,6 @@ describe('util', function() {
// Chrome sometimes reports foo.js as foo.js/, so tolerate
// a trailing slash if present.
expect(privateUnderTest.util.jasmineFile()).toMatch(/util.js\/?$/);
expect(jasmine.private.util.jasmineFile()).toMatch(/jasmine.js\/?$/);
});
});
});

View File

@@ -1289,9 +1289,7 @@ describe('Env integration', function() {
await env.execute();
expect(reporter.specDone).toHaveBeenCalledTimes(1);
const event = reporter.specDone.calls.argsFor(0)[0];
jasmine.debugLog(
'Spec result: ' + jasmine.private.basicPrettyPrinter(event)
);
jasmine.debugLog('Spec result: ' + jasmine.pp(event));
expect(event).toEqual(jasmine.objectContaining({ status: 'passed' }));
jasmine.clock().tick(1);

View File

@@ -24,7 +24,6 @@ describe('The jasmine namespace', function() {
'getEnv',
'isSpy',
'ParallelReportDispatcher',
'private',
'spyOnGlobalErrorsAsync',
'Timer',
'version',

View File

@@ -1,9 +1,11 @@
(function() {
// By the time onload is called, jasmineRequire will be redefined to point
// to the Jasmine source files (and not jasmine.js). So re-require
window.jasmineUnderTest = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmineUnderTest);
// By the time onload is called, getJasmineRequireObj() and
// getJasmineHtmlRequireObj() will be redefined to point
// to the Jasmine source files (and not jasmine.js). So re-require.
const jasmineRequire = getJasmineRequireObj();
const coreUnderTest = jasmineRequire.core(jasmineRequire);
window.jasmineUnderTest = coreUnderTest.jasmine;
window.privateUnderTest = coreUnderTest.private;
// Alias the private namespace so tests can be less verbose
window.privateUnderTest = window.jasmineUnderTest.private;
getJasmineHtmlRequireObj().html(jasmineUnderTest, privateUnderTest);
})();

View File

@@ -42,9 +42,9 @@
: 'Expected runnable "' +
fullName +
'" to have failures ' +
jasmine.private.basicPrettyPrinter(expectedFailures) +
jasmine.pp(expectedFailures) +
' but it had ' +
jasmine.private.basicPrettyPrinter(foundFailures)
jasmine.pp(foundFailures)
};
}
};

View File

@@ -7,24 +7,29 @@
'../../src/core/requireCore.js'
));
// Individual source files call getJasmineRequireObj. It's normally defined
// by requireCore.js which is concatenated into jasmine.js before other source
// files. Since we're bypassing that mechanism, we need to provide our own.
global.getJasmineRequireObj = function() {
return jasmineUnderTestRequire;
};
function getSourceFiles() {
const globs = ['../../src/core/**/*.js', '../../src/version.js'];
const srcFiles = globs.flatMap(g => glob.sync(g, { cwd: __dirname }));
const srcFiles = [
...glob.sync('../../src/core/**/*.js', {
ignore: '../../src/core/requireSuffix.js',
cwd: __dirname
}),
'../../src/version.js',
'../../src/core/requireCore.js'
];
for (const file of srcFiles) {
require(file);
}
for (const file of srcFiles) {
require(file);
}
getSourceFiles();
global.jasmineUnderTest = jasmineUnderTestRequire.core(
jasmineUnderTestRequire
);
delete global.getJasmineRequireObj;
// Alias the private namespace so tests can be less verbose
global.privateUnderTest = global.jasmineUnderTest.private;
const built = jasmineUnderTestRequire.core(jasmineUnderTestRequire);
global.jasmineUnderTest = built.jasmine;
global.privateUnderTest = built.private;
})();

View File

@@ -77,7 +77,7 @@ describe('npm package', function() {
});
it('has bootFiles', function() {
expect(this.packagedCore.files.bootFiles).toEqual(['boot0.js', 'boot1.js']);
expect(this.packagedCore.files.bootFiles).toEqual(['boot.js']);
for (const fileName of this.packagedCore.files.bootFiles) {
expect(fileName).toExistInPath(this.packagedCore.files.bootDir);

View File

@@ -12,7 +12,9 @@ module.exports = {
'core/**/*.js',
'html/**/*.js',
'**/*.js',
'!boot/**.js'
'!boot/**.js',
'!core/requireSuffix.js',
'!html/requireSuffix.js'
],
specDir: 'spec',
specFiles: ['**/*[Ss]pec.js', '!npmPackage/**/*'],