From 42e6c45efa8c427fc8bd612d587a2f32d9aafa73 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 29 Nov 2021 18:49:05 -0800 Subject: [PATCH] Allow use without creating globals * Fixes #1235 --- Gruntfile.js | 14 ++++++- lib/jasmine-core.js | 38 ++++++++++++++++++- lib/jasmine-core/jasmine.js | 2 + package.json | 1 + spec/core/JsApiReporterSpec.js | 2 +- spec/core/QueueRunnerSpec.js | 24 ++++++------ spec/core/TimerSpec.js | 2 + spec/core/TreeProcessorSpec.js | 22 +++++------ spec/core/integration/EnvSpec.js | 2 +- spec/core/matchers/DiffBuilderSpec.js | 4 +- spec/core/matchers/matchersUtilSpec.js | 2 +- .../matchers/toHaveBeenCalledBeforeSpec.js | 4 +- spec/html/HtmlReporterSpec.js | 4 -- spec/npmPackage/npmPackageSpec.js | 2 +- src/core/CompleteOnFirstErrorSkipPolicy.js | 2 + 15 files changed, 88 insertions(+), 37 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index cef1eb15..9a04fccb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -28,7 +28,8 @@ module.exports = function(grunt) { grunt.registerTask("execSpecsInNode", "Run Jasmine core specs in Node.js", function() { - var done = this.async(), + verifyNoGlobals(() => require('./lib/jasmine-core.js').noGlobals()); + const done = this.async(), Jasmine = require('jasmine'), jasmineCore = require('./lib/jasmine-core.js'), jasmine = new Jasmine({jasmineCore: jasmineCore}); @@ -52,3 +53,14 @@ module.exports = function(grunt) { } ); }; + +function verifyNoGlobals(fn) { + const initialGlobals = Object.keys(global); + fn(); + + const extras = Object.keys(global).filter(k => !initialGlobals.includes(k)); + + if (extras.length !== 0) { + throw new Error('Globals were unexpectedly created: ' + extras.join(', ')); + } +} diff --git a/lib/jasmine-core.js b/lib/jasmine-core.js index 886b7920..314ff9e7 100644 --- a/lib/jasmine-core.js +++ b/lib/jasmine-core.js @@ -1,6 +1,42 @@ -module.exports = require("./jasmine-core/jasmine.js"); +/** + * Note: Only available on Node. + * @module jasmine-core + */ + +const jasmineRequire = require('./jasmine-core/jasmine.js'); +module.exports = jasmineRequire; + +/** + * Boots a copy of Jasmine and returns an object as described in {@link jasmine}. + * @type {function} + * @return {jasmine} + */ module.exports.boot = require('./jasmine-core/node_boot.js'); +/** + * Boots a copy of Jasmine and returns an object containing the properties + * that would normally be added to the global object. If noGlobals is called + * multiple times, the same object is returned every time. + * + * Do not call boot() if you also call noGlobals(). + * + * @example + * const {describe, beforeEach, it, expect, jasmine} = require('jasmine-core').noGlobals(); + */ +module.exports.noGlobals = (function() { + let jasmineInterface; + + return function bootWithoutGlobals() { + if (!jasmineInterface) { + const jasmine = jasmineRequire.core(jasmineRequire); + const env = jasmine.getEnv({ suppressLoadErrors: true }); + jasmineInterface = jasmineRequire.interface(jasmine, env); + } + + return jasmineInterface; + }; +}()); + var path = require('path'), fs = require('fs'); diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index d93e08c1..947a8b7f 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -3482,6 +3482,8 @@ getJasmineRequireObj().CompleteOnFirstErrorSkipPolicy = function(j$) { } CompleteOnFirstErrorSkipPolicy.prototype.skipTo = function(lastRanFnIx) { + let i; + for ( i = lastRanFnIx + 1; i < this.queueableFns_.length && this.shouldSkip_(i); diff --git a/package.json b/package.json index 4035265c..7f8d3815 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "args": "none" } ], + "no-implicit-globals": "error", "block-spacing": "error", "func-call-spacing": [ "error", diff --git a/spec/core/JsApiReporterSpec.js b/spec/core/JsApiReporterSpec.js index d0985a31..ea3e67b7 100644 --- a/spec/core/JsApiReporterSpec.js +++ b/spec/core/JsApiReporterSpec.js @@ -99,7 +99,7 @@ describe('JsApiReporter', function() { }); describe('#suiteResults', function() { - var reporter, suiteResult1, suiteResult2; + var reporter, suiteStarted1, suiteResult1, suiteResult2; beforeEach(function() { reporter = new jasmineUnderTest.JsApiReporter({}); suiteStarted1 = { diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index 34141f4f..5adf6ea7 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -471,20 +471,20 @@ describe('QueueRunner', function() { }, 100); return p1; } - }; - (queueableFn2 = { - fn: function() { - fnCallback(); - setTimeout(function() { - p2.resolveHandler(); - }, 100); - return p2; - } - }), - (queueRunner = new jasmineUnderTest.QueueRunner({ + }, + queueableFn2 = { + fn: function() { + fnCallback(); + setTimeout(function() { + p2.resolveHandler(); + }, 100); + return p2; + } + }, + queueRunner = new jasmineUnderTest.QueueRunner({ queueableFns: [queueableFn1, queueableFn2], onComplete: onComplete - })); + }); queueRunner.execute(); expect(fnCallback).not.toHaveBeenCalled(); diff --git a/spec/core/TimerSpec.js b/spec/core/TimerSpec.js index f733f0d9..39d74dc6 100644 --- a/spec/core/TimerSpec.js +++ b/spec/core/TimerSpec.js @@ -14,10 +14,12 @@ describe('Timer', function() { describe('when date is stubbed, perhaps by other testing helpers', function() { var origDate = Date; beforeEach(function() { + // eslint-disable-next-line no-implicit-globals Date = jasmine.createSpy('date spy'); }); afterEach(function() { + // eslint-disable-next-line no-implicit-globals Date = origDate; }); diff --git a/spec/core/TreeProcessorSpec.js b/spec/core/TreeProcessorSpec.js index 7ada587d..c33a0000 100644 --- a/spec/core/TreeProcessorSpec.js +++ b/spec/core/TreeProcessorSpec.js @@ -513,20 +513,20 @@ describe('TreeProcessor', function() { it('runs afterAlls for a node with children', function() { var leaf = new Leaf(), - afterAllFns = [{ fn: 'afterAll1' }, { fn: 'afterAll2' }]; - (node = new Node({ - children: [leaf], - afterAllFns - })), - (root = new Node({ children: [node] })), - (queueRunner = jasmine.createSpy('queueRunner')), - (processor = new jasmineUnderTest.TreeProcessor({ + afterAllFns = [{ fn: 'afterAll1' }, { fn: 'afterAll2' }], + node = new Node({ + children: [leaf], + afterAllFns + }), + root = new Node({ children: [node] }), + queueRunner = jasmine.createSpy('queueRunner'), + processor = new jasmineUnderTest.TreeProcessor({ tree: root, runnableIds: [node.id], queueRunnerFactory: queueRunner - })), - (treeComplete = jasmine.createSpy('treeComplete')), - (nodeDone = jasmine.createSpy('nodeDone')); + }), + treeComplete = jasmine.createSpy('treeComplete'), + nodeDone = jasmine.createSpy('nodeDone'); processor.execute(treeComplete); var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns; diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 45846e4f..b7b607df 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -3427,7 +3427,7 @@ describe('Env integration', function() { const spiedOnAllFuncs = { foo: function() {} }; env.spyOnAllFunctions(spiedOnAllFuncs); - for (spy of [ + for (const spy of [ createSpySpy, spiedOn.foo, spyObj.foo, diff --git a/spec/core/matchers/DiffBuilderSpec.js b/spec/core/matchers/DiffBuilderSpec.js index d1a3d884..840eff68 100644 --- a/spec/core/matchers/DiffBuilderSpec.js +++ b/spec/core/matchers/DiffBuilderSpec.js @@ -112,7 +112,7 @@ describe('DiffBuilder', function() { return '[number:' + x + ']'; } }; - prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]); + const prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]); var diffBuilder = new jasmineUnderTest.DiffBuilder({ prettyPrinter: prettyPrinter }); @@ -131,7 +131,7 @@ describe('DiffBuilder', function() { return '[thing with a=' + x.a + ', b=' + JSON.stringify(x.b) + ']'; } }; - prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]); + const prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]); var diffBuilder = new jasmineUnderTest.DiffBuilder({ prettyPrinter: prettyPrinter }); diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index a01c16e4..b9dc1727 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -94,7 +94,7 @@ describe('matchersUtil', function() { }); it('fails for Arrays that have different lengths', function() { - matchersUtil = new jasmineUnderTest.MatchersUtil(); + const matchersUtil = new jasmineUnderTest.MatchersUtil(); expect(matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false); }); diff --git a/spec/core/matchers/toHaveBeenCalledBeforeSpec.js b/spec/core/matchers/toHaveBeenCalledBeforeSpec.js index 2bf316e3..b8ad4951 100644 --- a/spec/core/matchers/toHaveBeenCalledBeforeSpec.js +++ b/spec/core/matchers/toHaveBeenCalledBeforeSpec.js @@ -30,7 +30,7 @@ describe('toHaveBeenCalledBefore', function() { secondSpy(); - result = matcher.compare(firstSpy, secondSpy); + const result = matcher.compare(firstSpy, secondSpy); expect(result.pass).toBe(false); expect(result.message).toMatch( /Expected spy first spy to have been called./ @@ -44,7 +44,7 @@ describe('toHaveBeenCalledBefore', function() { firstSpy(); - result = matcher.compare(firstSpy, secondSpy); + const result = matcher.compare(firstSpy, secondSpy); expect(result.pass).toBe(false); expect(result.message).toMatch( /Expected spy second spy to have been called./ diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index 19e2ef97..32350f81 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -73,10 +73,6 @@ describe('HtmlReporter', function() { describe('and no expectations ran', function() { var container, reporter; beforeEach(function() { - if (typeof console === 'undefined') { - console = { warn: function() {}, error: function() {} }; - } - container = document.createElement('div'); reporter = new jasmineUnderTest.HtmlReporter({ env: env, diff --git a/spec/npmPackage/npmPackageSpec.js b/spec/npmPackage/npmPackageSpec.js index be141dde..f5995c92 100644 --- a/spec/npmPackage/npmPackageSpec.js +++ b/spec/npmPackage/npmPackageSpec.js @@ -143,7 +143,7 @@ describe('npm package', function() { j; for (j = 0; j < dirents.length; j++) { - dirent = dirents[j]; + const dirent = dirents[j]; if (dirent.isDirectory()) { getFiles(path.resolve(dir, dirent.name)); diff --git a/src/core/CompleteOnFirstErrorSkipPolicy.js b/src/core/CompleteOnFirstErrorSkipPolicy.js index 5be5c79f..1dcc4019 100644 --- a/src/core/CompleteOnFirstErrorSkipPolicy.js +++ b/src/core/CompleteOnFirstErrorSkipPolicy.js @@ -5,6 +5,8 @@ getJasmineRequireObj().CompleteOnFirstErrorSkipPolicy = function(j$) { } CompleteOnFirstErrorSkipPolicy.prototype.skipTo = function(lastRanFnIx) { + let i; + for ( i = lastRanFnIx + 1; i < this.queueableFns_.length && this.shouldSkip_(i);