From 8ad4f031604910f9e889a1ccd57998947e74e2af Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 18 Oct 2023 12:42:12 +0200 Subject: [PATCH 1/4] Use Rsync for syncing docs dir cp -rl was wonky on macOS. rsync worked much better. Makes the release available on http://127.0.0.1:4000/releases/dev/release/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f97c4b073..bee6012ff 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}'", From cffc1d4899132c43705843ba66484e7cb1b2020f Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 18 Oct 2023 14:07:00 +0200 Subject: [PATCH 2/4] Remove Husky in favor of simple script Husky has not been working for some time. Has turned way too complicated --- package-lock.json | 19 ------------------- package.json | 11 +++-------- scripts/hooks/pre-commit | 1 + 3 files changed, 4 insertions(+), 27 deletions(-) create mode 100755 scripts/hooks/pre-commit 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 bee6012ff..bf248ab90 100644 --- a/package.json +++ b/package.json @@ -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 $@ From cb3d189a9bf541b70e6ac8821f6756d60ebf00e3 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 18 Oct 2023 13:34:13 +0200 Subject: [PATCH 3/4] Update typescript article with how replace.usingAccessor improves DI --- .gitignore | 1 + docs/_howto/typescript-swc.md | 47 ++++++++++++++++++++++++-- docs/assets/css/main.scss | 4 +++ docs/release-source/release/sandbox.md | 2 +- 4 files changed, 51 insertions(+), 3 deletions(-) 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/docs/_howto/typescript-swc.md b/docs/_howto/typescript-swc.md index 7aba01590..d67fddf65 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,6 +227,47 @@ 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] @@ -261,5 +304,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);` From 269267420dfb6ecee711a98a57c60fb28b876e2c Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 18 Oct 2023 14:06:22 +0200 Subject: [PATCH 4/4] Fix Prettier config --- .prettierignore | 1 + docs/_howto/typescript-swc.md | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) 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 d67fddf65..c05ea46ee 100644 --- a/docs/_howto/typescript-swc.md +++ b/docs/_howto/typescript-swc.md @@ -249,8 +249,10 @@ export const myMocks = { set toBeMocked(mockImplementation) { toBeMocked = mockImplementation; }, - get toBeMocked(){ return _toBeMocked; } -} + get toBeMocked() { + return _toBeMocked; + }, +}; ``` **main.spec.ts** @@ -272,7 +274,7 @@ describe("main", () => { > [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", () => {