Merge branch 'main' into parallel

This commit is contained in:
Steve Gravrock
2022-09-17 13:26:37 -07:00
14 changed files with 195 additions and 109 deletions

View File

@@ -18,12 +18,11 @@ copied to `jasmine.js` when the distribution is built. When releasing a new
version, update `package.json` with the new version and `npm run build` to version, update `package.json` with the new version and `npm run build` to
update the gem version number. update the gem version number.
Note that Jasmine should only use the "patch" version number in the following cases: Note that Jasmine should only use the "patch" version number if the new release
contains only bug fixes.
* Changes related to packaging for a specific binding library (npm or browser-runner) When `jasmine-core` revs its major or minor version, the `jasmine` NPM package
* Fixes for regressions. should also rev to that version.
When jasmine-core revs its major or minor version, the binding libraries should also rev to that version.
## Release ## Release
@@ -61,20 +60,13 @@ for instructions.
1. `rake release[${version}]` to copy the current edge docs to the new version 1. `rake release[${version}]` to copy the current edge docs to the new version
1. Commit and push. 1. Commit and push.
### Release the binding libraries ### Release the `jasmine` NPM package
#### NPM See <https://github.com/jasmine/jasmine-npm/blob/main/RELEASE.md>.
1. Create release notes using Anchorman as above ### Publish the GitHub release
1. In `package.json`, update both the package version and the jasmine-core dependency version
1. Commit and push.
1. Wait for Circle CI to go green again.
1. `grunt release `. (Note: This will publish the package by running `npm publish`.)
### Finally
For each of the above GitHub repos:
1. Visit the releases page and find the tag just published. 1. Visit the releases page and find the tag just published.
1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes. 2. Paste in a link to the correct release notes for this release.
1. If it is a pre-release, mark it as such. 3. If it is a pre-release, mark it as such.
1. For core, attach the standalone zipfile. 4. Attach the standalone zipfile.

View File

@@ -1,24 +1,24 @@
function Player() { class Player {
} play(song) {
Player.prototype.play = function(song) { this.currentlyPlayingSong = song;
this.currentlyPlayingSong = song; this.isPlaying = true;
this.isPlaying = true;
};
Player.prototype.pause = function() {
this.isPlaying = false;
};
Player.prototype.resume = function() {
if (this.isPlaying) {
throw new Error("song is already playing");
} }
this.isPlaying = true; pause() {
}; this.isPlaying = false;
}
Player.prototype.makeFavorite = function() { resume() {
this.currentlyPlayingSong.persistFavoriteStatus(true); if (this.isPlaying) {
}; throw new Error('song is already playing');
}
this.isPlaying = true;
}
makeFavorite() {
this.currentlyPlayingSong.persistFavoriteStatus(true);
}
}
module.exports = Player; module.exports = Player;

View File

@@ -1,9 +1,8 @@
function Song() { class Song {
persistFavoriteStatus(value) {
// something complicated
throw new Error('not yet implemented');
}
} }
Song.prototype.persistFavoriteStatus = function(value) {
// something complicated
throw new Error("not yet implemented");
};
module.exports = Song; module.exports = Song;

View File

@@ -3,11 +3,11 @@ beforeEach(function () {
toBePlaying: function () { toBePlaying: function () {
return { return {
compare: function (actual, expected) { compare: function (actual, expected) {
var player = actual; const player = actual;
return { return {
pass: player.currentlyPlayingSong === expected && player.isPlaying pass: player.currentlyPlayingSong === expected && player.isPlaying
} };
} }
}; };
} }

View File

@@ -1,36 +1,37 @@
describe("Player", function() { const Player = require('../../lib/jasmine_examples/Player');
var Player = require('../../lib/jasmine_examples/Player'); const Song = require('../../lib/jasmine_examples/Song');
var Song = require('../../lib/jasmine_examples/Song');
var player; describe('Player', function() {
var song; let player;
let song;
beforeEach(function() { beforeEach(function() {
player = new Player(); player = new Player();
song = new Song(); song = new Song();
}); });
it("should be able to play a Song", function() { it('should be able to play a Song', function() {
player.play(song); player.play(song);
expect(player.currentlyPlayingSong).toEqual(song); expect(player.currentlyPlayingSong).toEqual(song);
//demonstrates use of custom matcher // demonstrates use of custom matcher
expect(player).toBePlaying(song); expect(player).toBePlaying(song);
}); });
describe("when song has been paused", function() { describe('when song has been paused', function() {
beforeEach(function() { beforeEach(function() {
player.play(song); player.play(song);
player.pause(); player.pause();
}); });
it("should indicate that the song is currently paused", function() { it('should indicate that the song is currently paused', function() {
expect(player.isPlaying).toBeFalsy(); expect(player.isPlaying).toBeFalsy();
// demonstrates use of 'not' with a custom matcher // demonstrates use of 'not' with a custom matcher
expect(player).not.toBePlaying(song); expect(player).not.toBePlaying(song);
}); });
it("should be possible to resume", function() { it('should be possible to resume', function() {
player.resume(); player.resume();
expect(player.isPlaying).toBeTruthy(); expect(player.isPlaying).toBeTruthy();
expect(player.currentlyPlayingSong).toEqual(song); expect(player.currentlyPlayingSong).toEqual(song);
@@ -38,7 +39,7 @@ describe("Player", function() {
}); });
// demonstrates use of spies to intercept and test method calls // demonstrates use of spies to intercept and test method calls
it("tells the current song if the user has made it a favorite", function() { it('tells the current song if the user has made it a favorite', function() {
spyOn(song, 'persistFavoriteStatus'); spyOn(song, 'persistFavoriteStatus');
player.play(song); player.play(song);
@@ -48,13 +49,13 @@ describe("Player", function() {
}); });
//demonstrates use of expected exceptions //demonstrates use of expected exceptions
describe("#resume", function() { describe('#resume', function() {
it("should throw an exception if song is already playing", function() { it('should throw an exception if song is already playing', function() {
player.play(song); player.play(song);
expect(function() { expect(function() {
player.resume(); player.resume();
}).toThrowError("song is already playing"); }).toThrowError('song is already playing');
}); });
}); });
}); });

View File

@@ -1,34 +1,34 @@
describe("Player", function() { describe('Player', function() {
var player; let player;
var song; let song;
beforeEach(function() { beforeEach(function() {
player = new Player(); player = new Player();
song = new Song(); song = new Song();
}); });
it("should be able to play a Song", function() { it('should be able to play a Song', function() {
player.play(song); player.play(song);
expect(player.currentlyPlayingSong).toEqual(song); expect(player.currentlyPlayingSong).toEqual(song);
//demonstrates use of custom matcher // demonstrates use of custom matcher
expect(player).toBePlaying(song); expect(player).toBePlaying(song);
}); });
describe("when song has been paused", function() { describe('when song has been paused', function() {
beforeEach(function() { beforeEach(function() {
player.play(song); player.play(song);
player.pause(); player.pause();
}); });
it("should indicate that the song is currently paused", function() { it('should indicate that the song is currently paused', function() {
expect(player.isPlaying).toBeFalsy(); expect(player.isPlaying).toBeFalsy();
// demonstrates use of 'not' with a custom matcher // demonstrates use of 'not' with a custom matcher
expect(player).not.toBePlaying(song); expect(player).not.toBePlaying(song);
}); });
it("should be possible to resume", function() { it('should be possible to resume', function() {
player.resume(); player.resume();
expect(player.isPlaying).toBeTruthy(); expect(player.isPlaying).toBeTruthy();
expect(player.currentlyPlayingSong).toEqual(song); expect(player.currentlyPlayingSong).toEqual(song);
@@ -36,7 +36,7 @@ describe("Player", function() {
}); });
// demonstrates use of spies to intercept and test method calls // demonstrates use of spies to intercept and test method calls
it("tells the current song if the user has made it a favorite", function() { it('tells the current song if the user has made it a favorite', function() {
spyOn(song, 'persistFavoriteStatus'); spyOn(song, 'persistFavoriteStatus');
player.play(song); player.play(song);
@@ -46,13 +46,13 @@ describe("Player", function() {
}); });
//demonstrates use of expected exceptions //demonstrates use of expected exceptions
describe("#resume", function() { describe('#resume', function() {
it("should throw an exception if song is already playing", function() { it('should throw an exception if song is already playing', function() {
player.play(song); player.play(song);
expect(function() { expect(function() {
player.resume(); player.resume();
}).toThrowError("song is already playing"); }).toThrowError('song is already playing');
}); });
}); });
}); });

View File

@@ -3,7 +3,7 @@ beforeEach(function () {
toBePlaying: function () { toBePlaying: function () {
return { return {
compare: function (actual, expected) { compare: function (actual, expected) {
var player = actual; const player = actual;
return { return {
pass: player.currentlyPlayingSong === expected && player.isPlaying pass: player.currentlyPlayingSong === expected && player.isPlaying

View File

@@ -1,22 +1,22 @@
function Player() { class Player {
} play(song) {
Player.prototype.play = function(song) { this.currentlyPlayingSong = song;
this.currentlyPlayingSong = song; this.isPlaying = true;
this.isPlaying = true;
};
Player.prototype.pause = function() {
this.isPlaying = false;
};
Player.prototype.resume = function() {
if (this.isPlaying) {
throw new Error("song is already playing");
} }
this.isPlaying = true; pause() {
}; this.isPlaying = false;
}
Player.prototype.makeFavorite = function() { resume() {
this.currentlyPlayingSong.persistFavoriteStatus(true); if (this.isPlaying) {
}; throw new Error('song is already playing');
}
this.isPlaying = true;
}
makeFavorite() {
this.currentlyPlayingSong.persistFavoriteStatus(true);
}
}

View File

@@ -1,7 +1,6 @@
function Song() { class Song {
persistFavoriteStatus(value) {
// something complicated
throw new Error('not yet implemented');
}
} }
Song.prototype.persistFavoriteStatus = function(value) {
// something complicated
throw new Error("not yet implemented");
};

View File

@@ -8454,7 +8454,7 @@ getJasmineRequireObj().Runner = function(j$) {
const order = new j$.Order({ const order = new j$.Order({
random: config.random, random: config.random,
seed: config.seed seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
}); });
const processor = new j$.TreeProcessor({ const processor = new j$.TreeProcessor({
@@ -9904,11 +9904,6 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
suite.exclude(); suite.exclude();
} }
this.addSpecsToSuite_(suite, definitionFn); this.addSpecsToSuite_(suite, definitionFn);
if (suite.parentSuite && !suite.children.length) {
throw new Error(
`describe with no children (describe() or it()): ${suite.getFullName()}`
);
}
return suite; return suite;
} }
@@ -10055,11 +10050,19 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
const parentSuite = this.currentDeclarationSuite_; const parentSuite = this.currentDeclarationSuite_;
parentSuite.addChild(suite); parentSuite.addChild(suite);
this.currentDeclarationSuite_ = suite; this.currentDeclarationSuite_ = suite;
let threw = false;
try { try {
definitionFn(); definitionFn();
} catch (e) { } catch (e) {
suite.handleException(e); suite.handleException(e);
threw = true;
}
if (suite.parentSuite && !suite.children.length && !threw) {
throw new Error(
`describe with no children (describe() or it()): ${suite.getFullName()}`
);
} }
this.currentDeclarationSuite_ = parentSuite; this.currentDeclarationSuite_ = parentSuite;

28
release_notes/4.4.0.md Normal file
View File

@@ -0,0 +1,28 @@
# Jasmine 4.4.0 Release Notes
## Changes
* Optimized the process of transitioning between specs in Node, Safari, and
Edge. This change reduces the run time of jasmine-core's own test suite by
50-70% in Node, about 20% in Edge, and 75-90% in Safari. Your results may
vary. In general, suites with many fast specs will see the greatest
performance improvement.
* Removed old code to support browsers that don't provide
addEventListener/removeEventListener.
## Supported environments
jasmine-core 4.4.0 has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------|
| Node | 12.17+, 14, 16, 18 |
| Safari | 14-15 |
| Chrome | 105 |
| Firefox | 91, 102, 104 |
| Edge | 104 |
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -2026,6 +2026,29 @@ describe('Env integration', function() {
expect(doneArg.order.seed).toEqual('123456'); expect(doneArg.order.seed).toEqual('123456');
}); });
it('coerces the random seed to a string if it is a number', async function() {
const reporter = jasmine.createSpyObj('fakeReporter', [
'jasmineStarted',
'jasmineDone',
'suiteStarted',
'suiteDone',
'specStarted',
'specDone'
]);
env.configure({ random: true, seed: 123456 });
env.addReporter(reporter);
env.configure({ random: true });
await env.execute();
expect(reporter.jasmineStarted).toHaveBeenCalled();
const startedArg = reporter.jasmineStarted.calls.argsFor(0)[0];
expect(startedArg.order.seed).toEqual('123456');
const doneArg = reporter.jasmineDone.calls.argsFor(0)[0];
expect(doneArg.order.seed).toEqual('123456');
});
it('should report pending spec messages', async function() { it('should report pending spec messages', async function() {
const reporter = jasmine.createSpyObj('fakeReporter', ['specDone']); const reporter = jasmine.createSpyObj('fakeReporter', ['specDone']);
@@ -3947,6 +3970,44 @@ describe('Env integration', function() {
}); });
}); });
it('reports a suite level error when a describe fn throws', async function() {
const reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
env.addReporter(reporter);
env.describe('throws before defining specs', function() {
throw new Error('nope');
});
env.describe('throws after defining specs', function() {
env.it('is a spec');
throw new Error('nope');
});
await env.execute();
expect(reporter.suiteDone).toHaveBeenCalledWith(
jasmine.objectContaining({
fullName: 'throws after defining specs',
failedExpectations: [
jasmine.objectContaining({
message: jasmine.stringContaining('Error: nope')
})
]
})
);
expect(reporter.suiteDone).toHaveBeenCalledWith(
jasmine.objectContaining({
fullName: 'throws after defining specs',
failedExpectations: [
jasmine.objectContaining({
message: jasmine.stringContaining('Error: nope')
})
]
})
);
});
function browserEventMethods() { function browserEventMethods() {
return { return {
addEventListener() {}, addEventListener() {},

View File

@@ -51,7 +51,7 @@ getJasmineRequireObj().Runner = function(j$) {
const order = new j$.Order({ const order = new j$.Order({
random: config.random, random: config.random,
seed: config.seed seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
}); });
const processor = new j$.TreeProcessor({ const processor = new j$.TreeProcessor({

View File

@@ -38,11 +38,6 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
suite.exclude(); suite.exclude();
} }
this.addSpecsToSuite_(suite, definitionFn); this.addSpecsToSuite_(suite, definitionFn);
if (suite.parentSuite && !suite.children.length) {
throw new Error(
`describe with no children (describe() or it()): ${suite.getFullName()}`
);
}
return suite; return suite;
} }
@@ -189,11 +184,19 @@ getJasmineRequireObj().SuiteBuilder = function(j$) {
const parentSuite = this.currentDeclarationSuite_; const parentSuite = this.currentDeclarationSuite_;
parentSuite.addChild(suite); parentSuite.addChild(suite);
this.currentDeclarationSuite_ = suite; this.currentDeclarationSuite_ = suite;
let threw = false;
try { try {
definitionFn(); definitionFn();
} catch (e) { } catch (e) {
suite.handleException(e); suite.handleException(e);
threw = true;
}
if (suite.parentSuite && !suite.children.length && !threw) {
throw new Error(
`describe with no children (describe() or it()): ${suite.getFullName()}`
);
} }
this.currentDeclarationSuite_ = parentSuite; this.currentDeclarationSuite_ = parentSuite;