diff --git a/.gitignore b/.gitignore index 8bdc7c79e..8fe05e9da 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ coverage/ _site docs/vendor/ vendor/ +.bundle diff --git a/.prettierignore b/.prettierignore index 7f6d127cd..d36522fec 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,3 +6,4 @@ tmp/ docs/_site/ docs/js/ docs/assets/js/ +vendor diff --git a/docs/_howto/typescript-swc.md b/docs/_howto/typescript-swc.md index 7aba01590..c05ea46ee 100644 --- a/docs/_howto/typescript-swc.md +++ b/docs/_howto/typescript-swc.md @@ -190,9 +190,11 @@ sandbox.replaceGetter(Other, "toBeMocked", () => stub); ## Use pure dependency injection +### Version 1 : full manual mode + > [Working code][pure-di] -This technique works regardless of language, module systems, bundlers and tool chains, but requires slight modifications of the SUT to allow modifying it. Sinon cannot help with resetting state automatically in this scenario. +This technique works regardless of language, module systems, bundlers and tool chains, but requires slight modifications of the SUT to allow modifying it. Sinon does not help in resetting state automatically in this scenario. **other.ts** @@ -225,11 +227,54 @@ describe("main", () => { }); ``` +### Version 2: using Sinon's auto-cleanup + +> [Working code][pure-di-with-auto-cleanup] + +This is a slight variation of the fully manual dependency injection version, but with a twist to +make it nicer. Sinon 16.1 gained the ability to assign and restore values that were defined +using _accessors_. That means, that if you expose an object with setters and getters for props +you would like to replace, you can get Sinon to clean up after you. The example above becomes much nicer: + +**other.ts** + +```typescript +function _toBeMocked() { + return "I am the original function"; +} + +export let toBeMocked = _toBeMocked; + +export const myMocks = { + set toBeMocked(mockImplementation) { + toBeMocked = mockImplementation; + }, + get toBeMocked() { + return _toBeMocked; + }, +}; +``` + +**main.spec.ts** + +```typescript +describe("main", () => { + + after(() => sandbox.restore()) + + it("should mock", () => { + mocked = sandbox.fake.returns("mocked"); + sandbox.replace.usingAccessor(Other.myMocks, 'toBeMocked', mocked) + main(); + expect(mocked.called).to.be.true; + }); +``` + ## Hooking into Node's module loading > [Working code][cjs-mocking] -This is what [the article on _targetting the link seams_][link-seams-cjs] is about. The only difference here is using Quibble instead of Proxyquire. Quibble is slightly terser and also supports being used as a ESM _loader_, making it a bit more modern and useful. The end result: +This is what [the article on _targetting the link seams_][link-seams-cjs] is about. The only difference here is using Quibble instead of Proxyquire. Quibble is slightly terser and also supports being used as a ESM _loader_, making it a bit more modern and useful. The end result looks like this: ```typescript describe("main module", () => { @@ -261,5 +306,5 @@ As can be seen, there are lots of different paths to walk in order to achieve th [sut]: http://xunitpatterns.com/SUT.html [require-hook]: https://levelup.gitconnected.com/how-to-add-hooks-to-node-js-require-function-dee7acd12698 [swc-mutable-export]: https://github.com/fatso83/sinon-swc-bug/tree/swc-with-mutable-exports -[pure-di]: https://github.com/fatso83/sinon-swc-bug/tree/pure-di +[pure-di-with-auto-cleanup]: https://github.com/fatso83/sinon-swc-bug/tree/auto-cleanup-di [cjs-mocking]: https://github.com/fatso83/sinon-swc-bug/tree/cjs-mocking diff --git a/docs/assets/css/main.scss b/docs/assets/css/main.scss index 9a99d71a2..eff6474f3 100644 --- a/docs/assets/css/main.scss +++ b/docs/assets/css/main.scss @@ -195,6 +195,10 @@ body { // Content .content { padding: 60px 0px; + + & h5 { + font-weight: 600; // make h5 visible: otherwise no difference is shown + } } // Pages diff --git a/docs/release-source/release/sandbox.md b/docs/release-source/release/sandbox.md index f801b15d4..24e64e079 100644 --- a/docs/release-source/release/sandbox.md +++ b/docs/release-source/release/sandbox.md @@ -242,7 +242,7 @@ Usually one intends to _replace_ the value or getter of a field, but there are u ##### Use case: no-frills dependency injection in ESM with cleanup -One use case can be to conveniently allow ESM module stubbing using pure dependency injection, having Sinon help you with the cleanup, without resorting to external machinery such as module loaders or require hooks (see [#2403](https://github.com/sinonjs/sinon/issues/2403)). This would then work regardless of bundler, browser or server environment. +One use case can be to conveniently allow ESM module stubbing using pure dependency injection, having Sinon help you with the cleanup, without resorting to external machinery such as module loaders or require hooks (see [the case study on module mocking Typescript](/how-to/typescript-swc/#version-2-using-sinons-auto-cleanup) for an example). This approach works regardless of bundler, browser or server environment. #### `sandbox.replaceGetter(object, property, replacementFunction);` diff --git a/package-lock.json b/package-lock.json index 5af883b1d..0358c85c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,6 @@ "browserify": "^16.5.2", "debug": "^4.3.4", "dependency-check": "^4.1.0", - "husky": "^6.0.0", "lint-staged": "^13.2.0", "mocha": "^10.2.0", "mochify": "^9.2.0", @@ -4164,18 +4163,6 @@ "node": ">=14.18.0" } }, - "node_modules/husky": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", - "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -12492,12 +12479,6 @@ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "dev": true }, - "husky": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", - "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", - "dev": true - }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", diff --git a/package.json b/package.json index f97c4b073..bf248ab90 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "test": "npm run test-node && npm run test-headless && npm run test-webworker", "check-dependencies": "dependency-check package.json --no-dev --ignore-module esm", "build": "node ./build.cjs", - "dev-docs": "cd docs; cp -rl release-source releases/dev; npm run serve-docs", + "dev-docs": "cd docs; rsync -r --delete release-source/ releases/dev; npm run serve-docs", "build-docs": "cd docs; bundle exec jekyll build", "serve-docs": "cd docs; bundle exec jekyll serve --incremental --verbose --livereload", "lint": "eslint --max-warnings 101 '**/*.{js,cjs,mjs}'", @@ -58,7 +58,8 @@ "prettier:write": "prettier --write '**/*.{js,css,md}'", "preversion": "./scripts/preversion.sh", "version": "./scripts/version.sh", - "postversion": "./scripts/postversion.sh" + "postversion": "./scripts/postversion.sh", + "postinstall": "git config --replace-all core.hooksPath scripts/hooks" }, "nyc": { "instrument": false, @@ -69,7 +70,7 @@ ] }, "lint-staged": { - "*.{js,css,md}": "prettier --check", + "**/*.{js,css,md}": "prettier --write", "*.js": "eslint --quiet", "*.mjs": "eslint --quiet --ext mjs --parser-options=sourceType:module" }, @@ -92,7 +93,6 @@ "browserify": "^16.5.2", "debug": "^4.3.4", "dependency-check": "^4.1.0", - "husky": "^6.0.0", "lint-staged": "^13.2.0", "mocha": "^10.2.0", "mochify": "^9.2.0", @@ -137,10 +137,5 @@ "cache": true }, "mode": "auto" - }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" - } } } diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit new file mode 100755 index 000000000..10effaa37 --- /dev/null +++ b/scripts/hooks/pre-commit @@ -0,0 +1 @@ +npx lint-staged $@