diff --git a/.github/release-please/manifest.json b/.github/release-please/manifest.json index 8109666ec1..0ba0782ac5 100644 --- a/.github/release-please/manifest.json +++ b/.github/release-please/manifest.json @@ -1 +1 @@ -{".":"10.8.0"} +{".":"10.8.1"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4565cd3df1..f45fe6d6f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [10.8.1](https://github.com/mochajs/mocha/compare/v10.8.0...v10.8.1) (2024-10-29) + + +### 🩹 Fixes + +* handle case of invalid package.json with no explicit config ([#5198](https://github.com/mochajs/mocha/issues/5198)) ([f72bc17](https://github.com/mochajs/mocha/commit/f72bc17cb44164bcfff7abc83d0d37d99a061104)) +* Typos on mochajs.org ([#5237](https://github.com/mochajs/mocha/issues/5237)) ([d8ca270](https://github.com/mochajs/mocha/commit/d8ca270a960554c9d5c5fbf264e89d668d01ff0d)) +* use accurate test links in HTML reporter ([#5228](https://github.com/mochajs/mocha/issues/5228)) ([68803b6](https://github.com/mochajs/mocha/commit/68803b685d55dcccc51fa6ccfd27701cda4e26ed)) + ## [10.8.0](https://github.com/mochajs/mocha/compare/v10.7.3...v10.8.0) (2024-10-29) diff --git a/docs/index.md b/docs/index.md index b6990c4bf8..603e5e43cb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1170,7 +1170,7 @@ Cause Mocha to only run tests matching the given `regexp`, which is internally c Suppose, for example, you have "api" related tests, as well as "app" related tests, as shown in the following snippet; One could use `--grep api` or `--grep app` to run one or the other. The same goes for any other part of a suite or test-case title, `--grep users` would be valid as well, or even `--grep GET`. And another option with double quotes: `--grep "groupA|groupB"`.
-And for more complex criterias: `--grep "/get/i"`. Some shells as e.g. Git-Bash-for-Windows may require: `--grep "'/get/i'"`. Using flags other than the `ignoreCase /i` (especially `/g` and `/y`) may lead to unpredictable results. +And for more complex criteria: `--grep "/get/i"`. Some shells as e.g. Git-Bash-for-Windows may require: `--grep "'/get/i'"`. Using flags other than the `ignoreCase /i` (especially `/g` and `/y`) may lead to unpredictable results. ```js describe('api', function () { @@ -2248,7 +2248,7 @@ Mocha will also _merge_ any options found in `package.json` into its run-time co 1. Configuration file (`.mocharc.js`, `.mocharc.yml`, etc.) 1. `mocha` property of `package.json` -Options which can safely be repeated (e.g., `--require`) will be _concatenated_, with higher-priorty configuration sources appearing earlier in the list. For example, a `.mocharc.json` containing `"require": "bar"`, coupled with execution of `mocha --require foo`, would cause Mocha to require `foo`, then `bar`, in that order. +Options which can safely be repeated (e.g., `--require`) will be _concatenated_, with higher-priority configuration sources appearing earlier in the list. For example, a `.mocharc.json` containing `"require": "bar"`, coupled with execution of `mocha --require foo`, would cause Mocha to require `foo`, then `bar`, in that order. ### Extending Configuration @@ -2434,7 +2434,7 @@ or the [source](https://github.com/mochajs/mocha/blob/main/lib/mocha.js). [qunit]: https://qunitjs.com/ [selenium-webdriver-testing]: https://github.com/SeleniumHQ/selenium/blob/c10e8a955883f004452cdde18096d70738397788/javascript/node/selenium-webdriver/testing/index.js [should.js]: https://github.com/shouldjs/should.js -[superagent-docs-test]: https://visionmedia.github.io/superagent/docs/test.html +[superagent-docs-test]: https://ladjs.github.io/superagent/docs/test.html [superagent-makefile]: https://github.com/visionmedia/superagent/blob/master/Makefile [test-anything-protocol]: https://en.wikipedia.org/wiki/Test_Anything_Protocol [textmate-mocha]: https://github.com/mochajs/mocha.tmbundle diff --git a/lib/cli/options.js b/lib/cli/options.js index d238737d37..fc0c951a8c 100644 --- a/lib/cli/options.js +++ b/lib/cli/options.js @@ -181,8 +181,24 @@ const loadPkgRc = (args = {}) => { result = {}; const filepath = args.package || findUp.sync(mocharc.package); if (filepath) { + let configData; try { - const pkg = JSON.parse(fs.readFileSync(filepath, 'utf8')); + configData = fs.readFileSync(filepath, 'utf8'); + } catch (err) { + // If `args.package` was explicitly specified, throw an error + if (filepath == args.package) { + throw createUnparsableFileError( + `Unable to read ${filepath}: ${err}`, + filepath + ); + } else { + debug('failed to read default package.json at %s; ignoring', + filepath); + return result; + } + } + try { + const pkg = JSON.parse(configData); if (pkg.mocha) { debug('`mocha` prop of package.json parsed: %O', pkg.mocha); result = pkg.mocha; @@ -190,13 +206,11 @@ const loadPkgRc = (args = {}) => { debug('no config found in %s', filepath); } } catch (err) { - if (args.package) { - throw createUnparsableFileError( - `Unable to read/parse ${filepath}: ${err}`, - filepath - ); - } - debug('failed to read default package.json at %s; ignoring', filepath); + // If JSON failed to parse, throw an error. + throw createUnparsableFileError( + `Unable to parse ${filepath}: ${err}`, + filepath + ); } } return result; diff --git a/lib/reporters/html.js b/lib/reporters/html.js index c970fc05e9..7f4fa673fc 100644 --- a/lib/reporters/html.js +++ b/lib/reporters/html.js @@ -294,7 +294,7 @@ function makeUrl(s) { window.location.pathname + (search ? search + '&' : '?') + 'grep=' + - encodeURIComponent(escapeRe(s)) + encodeURIComponent(s) ); } @@ -304,7 +304,7 @@ function makeUrl(s) { * @param {Object} [suite] */ HTML.prototype.suiteURL = function (suite) { - return makeUrl(suite.fullTitle()); + return makeUrl('^' + escapeRe(suite.fullTitle()) + ' '); }; /** @@ -313,7 +313,7 @@ HTML.prototype.suiteURL = function (suite) { * @param {Object} [test] */ HTML.prototype.testURL = function (test) { - return makeUrl(test.fullTitle()); + return makeUrl('^' + escapeRe(test.fullTitle()) + '$'); }; /** diff --git a/package-lock.json b/package-lock.json index f2b14f8d59..2d02eee3a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mocha", - "version": "10.8.0", + "version": "10.8.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mocha", - "version": "10.8.0", + "version": "10.8.1", "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", diff --git a/package.json b/package.json index cf6efce959..0f86842389 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mocha", - "version": "10.8.0", + "version": "10.8.1", "type": "commonjs", "description": "simple, flexible, fun test framework", "keywords": [ diff --git a/test/node-unit/cli/options.spec.js b/test/node-unit/cli/options.spec.js index 60357d12ae..7c846a37ed 100644 --- a/test/node-unit/cli/options.spec.js +++ b/test/node-unit/cli/options.spec.js @@ -149,7 +149,7 @@ describe('options', function () { loadOptions('--package /something/wherever --require butts'); }, 'to throw', - 'Unable to read/parse /something/wherever: bad file message' + 'Unable to read /something/wherever: bad file message' ); }); }); @@ -199,6 +199,36 @@ describe('options', function () { }); }); + describe('when path to package.json unspecified and package.json exists but is invalid', function () { + beforeEach(function () { + const filepath = '/some/package.json'; + readFileSync = sinon.stub(); + // package.json + readFileSync + .onFirstCall() + .returns('{definitely-invalid'); + findConfig = sinon.stub().returns('/some/.mocharc.json'); + loadConfig = sinon.stub().returns({}); + findupSync = sinon.stub().returns(filepath); + loadOptions = proxyLoadOptions({ + readFileSync, + findConfig, + loadConfig, + findupSync + }); + }); + + it('should throw', function () { + expect( + () => { + loadOptions(); + }, + 'to throw', + /SyntaxError/, + ); + }); + }); + describe('when called with package = false (`--no-package`)', function () { let result; beforeEach(function () { @@ -287,7 +317,7 @@ describe('options', function () { }); it('should set config = false', function () { - expect(loadOptions(), 'to have property', 'config', false); + expect(result, 'to have property', 'config', false); }); });