diff --git a/package.json b/package.json index df3cdd87..970f4c1e 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "eslint-plugin-ghost": "3.5.0", "nodemon": "3.1.14", "should": "13.2.3", - "sinon": "21.0.3", "vitest": "4.1.2" }, "resolutions": { diff --git a/test/coverage-gaps.test.js b/test/coverage-gaps.test.js index d82cb473..53db9aca 100644 --- a/test/coverage-gaps.test.js +++ b/test/coverage-gaps.test.js @@ -4,7 +4,6 @@ const format = require('../lib/format'); const calcScore = require('../lib/utils/score-calculator'); const getPackageJSON = require('../lib/utils/package-json'); const BaseRule = require('../lib/ast-linter/rules/base'); -const sinon = require('sinon'); const NoLimitAllInGetHelper = require('../lib/ast-linter/rules/lint-no-limit-all-in-get-helper'); const NoLimitOver100InGetHelper = require('../lib/ast-linter/rules/lint-no-limit-over-100-in-get-helper'); const NoMultiParamConditionals = require('../lib/ast-linter/rules/lint-no-multi-param-conditionals'); @@ -152,10 +151,10 @@ describe('Coverage gaps', function () { }); it('supports unquoted limit values in get-helper limit-all and limit-over-100 checks', function () { - const limitAllLog = sinon.spy(); + const limitAllLogMock = vi.fn(); const limitAllRule = new NoLimitAllInGetHelper({ name: 'GS090-NO-LIMIT-ALL-IN-GET-HELPER', - log: limitAllLog, + log: limitAllLogMock, source: 'x', partials: [], helpers: [] @@ -167,12 +166,12 @@ describe('Coverage gaps', function () { hash: {pairs: [{key: 'limit', value: {original: 'all'}}]}, loc: {start: {line: 1, column: 0}, end: {line: 1, column: 1}} }); - limitAllLog.calledOnce.should.eql(true); + expect(limitAllLogMock).toHaveBeenCalledTimes(1); - const limitOver100Log = sinon.spy(); + const limitOver100LogMock = vi.fn(); const limitOver100Rule = new NoLimitOver100InGetHelper({ name: 'GS090-NO-LIMIT-OVER-100-IN-GET-HELPER', - log: limitOver100Log, + log: limitOver100LogMock, source: 'x', partials: [], helpers: [] @@ -184,14 +183,14 @@ describe('Coverage gaps', function () { hash: {pairs: [{key: 'limit', value: {original: '150'}}]}, loc: {start: {line: 1, column: 0}, end: {line: 1, column: 1}} }); - limitOver100Log.calledOnce.should.eql(true); + expect(limitOver100LogMock).toHaveBeenCalledTimes(1); }); it('reports multi-param unless conditionals', function () { - const logSpy = sinon.spy(); + const logMock = vi.fn(); const rule = new NoMultiParamConditionals({ name: 'no-multi-param-conditionals', - log: logSpy, + log: logMock, source: 'x', partials: [], helpers: [] @@ -203,6 +202,6 @@ describe('Coverage gaps', function () { loc: {start: {line: 1, column: 0}, end: {line: 1, column: 1}} }); - logSpy.calledOnce.should.eql(true); + expect(logMock).toHaveBeenCalledTimes(1); }); }); diff --git a/test/general.test.js b/test/general.test.js index 7f825d29..0cbcec7f 100644 --- a/test/general.test.js +++ b/test/general.test.js @@ -1,6 +1,5 @@ const path = require('path'); const fs = require('fs-extra'); -const sinon = require('sinon'); const errors = require('@tryghost/errors'); const {check, checkZip} = require('../lib'); const themePath = require('./utils').themePath; @@ -56,7 +55,7 @@ describe('Check zip', function () { }); it('wraps non-ghost errors as a check-zip validation error', async function () { - const isGhostErrorStub = sinon.stub(errors.utils, 'isGhostError').returns(false); + const isGhostErrorStub = vi.spyOn(errors.utils, 'isGhostError').mockReturnValue(false); try { await checkZip(themePath('030-assets/do_not_exist.zip')); @@ -67,7 +66,7 @@ describe('Check zip', function () { should.equal(err.message, 'Failed to check zip file'); should.equal(err.context, 'do_not_exist'); } finally { - isGhostErrorStub.restore(); + isGhostErrorStub.mockRestore(); } }); }); @@ -86,7 +85,8 @@ describe('Check zip', function () { it('removes extracted directory when checks fail', async function () { const readThemePath = require.resolve('../lib/read-theme'); const originalReadTheme = require(readThemePath); - const removeSpy = sinon.spy(fs, 'remove'); + const removeSpy = vi.spyOn(fs, 'remove'); + let removedPath; require.cache[readThemePath].exports = async function () { throw new Error('forced check failure'); @@ -99,15 +99,15 @@ describe('Check zip', function () { should.exist(err); should.equal(err.errorType, 'ValidationError'); should.equal(err.message, 'Failed theme files check'); + + expect(removeSpy).toHaveBeenCalledTimes(1); + removedPath = removeSpy.mock.calls[0][0]; + should.exist(removedPath); } finally { require.cache[readThemePath].exports = originalReadTheme; - removeSpy.restore(); + removeSpy.mockRestore(); } - removeSpy.calledOnce.should.eql(true); - const removedPath = removeSpy.firstCall.args[0]; - should.exist(removedPath); - const extractedThemePathExists = await fs.pathExists(removedPath); extractedThemePathExists.should.eql(false); }); diff --git a/test/read-zip.test.js b/test/read-zip.test.js index 38e974d3..3e9a40b8 100644 --- a/test/read-zip.test.js +++ b/test/read-zip.test.js @@ -1,4 +1,3 @@ -const sinon = require('sinon'); const fs = require('fs-extra'); const themePath = require('./utils').themePath; const readZip = require('../lib/read-zip'); @@ -16,21 +15,12 @@ function testReadZip(name) { } describe('Zip file handler can read zip files', function () { - let sandbox; const tempDirs = []; - beforeAll(function () { - sandbox = sinon.createSandbox(); - }); - afterAll(async function () { await Promise.all(tempDirs.map(dir => fs.remove(dir))); }); - afterEach(function () { - sandbox.restore(); - }); - it('Flat example: zip without folder should unzip and callback with a path', function () { return testReadZip('flat-example.zip') .then((zip) => { diff --git a/yarn.lock b/yarn.lock index 45b786f7..01f9e964 100644 --- a/yarn.lock +++ b/yarn.lock @@ -756,28 +756,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-7.2.0.tgz#7c594e1a64336d2008d99d814056d459421504d4" integrity sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw== -"@sinonjs/commons@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^15.1.1": - version "15.1.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz#e1a6f7171941aadcc31d2cea1744264d58b8b34c" - integrity sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw== - dependencies: - "@sinonjs/commons" "^3.0.1" - -"@sinonjs/samsam@^9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-9.0.3.tgz#da4cad6ee24ca0c9c205da16676f7d540df71f12" - integrity sha512-ZgYY7Dc2RW+OUdnZ1DEHg00lhRt+9BjymPKHog4PRFzr1U3MbK57+djmscWyKxzO1qfunHqs4N45WWyKIFKpiQ== - dependencies: - "@sinonjs/commons" "^3.0.1" - type-detect "^4.1.0" - "@standard-schema/spec@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" @@ -1906,11 +1884,6 @@ detect-libc@^2.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== -diff@^8.0.3: - version "8.0.4" - resolved "https://registry.yarnpkg.com/diff/-/diff-8.0.4.tgz#4f5baf3188b9b2431117b962eb20ba330fadf696" - integrity sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw== - dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -4169,17 +4142,6 @@ simple-update-notifier@^2.0.0: dependencies: semver "^7.5.3" -sinon@21.0.3: - version "21.0.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-21.0.3.tgz#fd3a2387ffe4fdbbfbbf3a0858f18d46c4acb34e" - integrity sha512-0x8TQFr8EjADhSME01u1ZK31yv2+bd6Z5NrBCHVM+n4qL1wFqbxftmeyi3bwlr49FbbzRfrqSFOpyHCOh/YmYA== - dependencies: - "@sinonjs/commons" "^3.0.1" - "@sinonjs/fake-timers" "^15.1.1" - "@sinonjs/samsam" "^9.0.3" - diff "^8.0.3" - supports-color "^7.2.0" - snake-case@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -4339,7 +4301,7 @@ supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0, supports-color@^7.2.0: +supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -4462,16 +4424,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-detect@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" - integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== - type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"