From 6be993c2a734e0e076905d85d5c659a8db3e8d1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 00:49:19 +0000 Subject: [PATCH 1/2] Bump sinon from 18.0.0 to 19.0.2 Bumps [sinon](https://github.com/sinonjs/sinon) from 18.0.0 to 19.0.2. - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md) - [Commits](https://github.com/sinonjs/sinon/compare/v18.0.0...v19.0.2) --- updated-dependencies: - dependency-name: sinon dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 86 ++++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff7b5d3f21..bba1ec32ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -154,7 +154,7 @@ "rewire": "^6.0.0", "seedrandom": "^3.0.5", "sharp": "^0.33.5", - "sinon": "^18.0.0", + "sinon": "^19.0.2", "sinon-chai": "^3.7.0", "std-mocks": "^2.0.0", "storybook": "^8.4.7", @@ -6619,9 +6619,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", - "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.1" @@ -6667,32 +6667,14 @@ } }, "node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", + "@sinonjs/commons": "^3.0.1", "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" + "type-detect": "^4.1.0" } }, "node_modules/@sinonjs/text-encoding": { @@ -19075,23 +19057,26 @@ "dev": true }, "node_modules/nise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", - "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", "dev": true, "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/text-encoding": "^0.7.2", + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", "just-extend": "^6.2.0", - "path-to-regexp": "^6.2.1" + "path-to-regexp": "^8.1.0" } }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "engines": { + "node": ">=16" + } }, "node_modules/no-case": { "version": "3.0.4", @@ -23488,17 +23473,17 @@ } }, "node_modules/sinon": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", - "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.2.0", - "nise": "^6.0.0", - "supports-color": "^7" + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" }, "funding": { "type": "opencollective", @@ -23515,6 +23500,15 @@ "sinon": ">=4.0.0" } }, + "node_modules/sinon/node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/sinon/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", diff --git a/package.json b/package.json index cee92d7013..a40cbd9fdd 100644 --- a/package.json +++ b/package.json @@ -209,7 +209,7 @@ "rewire": "^6.0.0", "seedrandom": "^3.0.5", "sharp": "^0.33.5", - "sinon": "^18.0.0", + "sinon": "^19.0.2", "sinon-chai": "^3.7.0", "std-mocks": "^2.0.0", "storybook": "^8.4.7", From edc288135272996e7a59b8800e0d7df1ca3f0370 Mon Sep 17 00:00:00 2001 From: Oliver Roberts Date: Tue, 10 Dec 2024 16:18:35 +0000 Subject: [PATCH 2/2] Refactor repo unit tests to work with `sinon` v19 fake timers --- src/apps/events/__test__/repos.test.js | 247 ++++++++++--------------- 1 file changed, 101 insertions(+), 146 deletions(-) diff --git a/src/apps/events/__test__/repos.test.js b/src/apps/events/__test__/repos.test.js index ccc29da431..9b59f2fac7 100644 --- a/src/apps/events/__test__/repos.test.js +++ b/src/apps/events/__test__/repos.test.js @@ -1,172 +1,127 @@ +const { expect } = require('chai') +const sinon = require('sinon') const proxyquire = require('proxyquire') +const authorisedRequestStub = sinon.stub() +const searchStub = sinon.stub() + +const { saveEvent, fetchEvent, getAllEvents, getActiveEvents } = proxyquire( + '../repos', + { + '../../lib/authorised-request': { + authorisedRequest: authorisedRequestStub, + }, + '../../modules/search/services': { search: searchStub }, + } +) + const config = require('../../../config') -const { search } = require('../../../modules/search/services') -const stubRequest = { session: { token: 'abcd' } } +describe('Event Service', () => { + const mockReq = { session: { token: 'test-token' } } -describe('Event repos', () => { beforeEach(() => { - this.authorisedRequestStub = sinon.stub().resolves() - this.searchSpy = sinon.spy(search) - this.repos = proxyquire('../repos', { - '../../lib/authorised-request': { - authorisedRequest: this.authorisedRequestStub, - }, - '../../modules/search/services': { - search: this.searchSpy, - }, - }) + sinon.reset() }) - describe('#saveEvent', () => { - context('when POST request', () => { - const eventMock = { name: 'Convention' } - - it('should call with POST method', () => { - this.repos.saveEvent(stubRequest, eventMock) - - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - sinon.match({ method: 'POST' }) - ) - }) - - it('should contain event form body', () => { - this.repos.saveEvent(stubRequest, eventMock) + afterEach(() => { + sinon.restore() + }) - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - sinon.match({ body: eventMock }) - ) + context('saveEvent', () => { + it('should POST new event', async () => { + const event = { name: 'Test Event' } + await saveEvent(mockReq, event) + expect(authorisedRequestStub).to.have.been.calledWith(mockReq, { + url: `${config.apiRoot}/v4/event`, + method: 'POST', + body: event, }) }) - context('when PATCH request', () => { - const eventMock = { id: '123', name: 'Convention' } - - it('should call with POST method', () => { - this.repos.saveEvent(stubRequest, eventMock) - - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - sinon.match({ method: 'PATCH' }) - ) - }) - - it('should set request URL to event URL', () => { - this.repos.saveEvent(stubRequest, eventMock) - - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - sinon.match({ url: `${config.apiRoot}/v4/event/${eventMock.id}` }) - ) - }) - - it('should contain event form body', () => { - const event = { name: 'Convention' } - this.repos.saveEvent(stubRequest, eventMock) - - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - sinon.match({ body: event }) - ) + it('should PATCH existing event', async () => { + const event = { id: 123, name: 'Test Event' } + await saveEvent(mockReq, event) + expect(authorisedRequestStub).to.have.been.calledWith(mockReq, { + url: `${config.apiRoot}/v4/event/${event.id}`, + method: 'PATCH', + body: event, }) }) }) - describe('#fetchEvent', () => { - it('should call with event URL', () => { - this.repos.fetchEvent(stubRequest, '123') - expect(this.authorisedRequestStub).to.be.calledWith( - stubRequest, - `${config.apiRoot}/v3/event/123` + context('fetchEvent', () => { + it('should fetch single event by id', async () => { + const id = '123' + await fetchEvent(mockReq, id) + expect(authorisedRequestStub).to.have.been.calledWith( + mockReq, + `${config.apiRoot}/v3/event/${id}` ) }) }) - describe('#getActiveEvents', () => { - context( - 'When there is a mix of active and inactive events on the server', - () => { - beforeEach(() => { - this.currentId = '3' - - this.eventCollection = { - results: [ - { - id: '2', - disabled_on: null, - }, - ], - } - - nock(config.apiRoot) - .post('/v3/search/event') - .reply(200, this.eventCollection) - }) - - context('and when asked for all active events', () => { - beforeEach(async () => { - const now = new Date() - this.clock = sinon.useFakeTimers(now.getTime()) - - this.currentFormattedTime = now.toISOString() - - this.events = await this.repos.getActiveEvents(stubRequest) - }) + context('getAllEvents', () => { + it('should fetch all events with limit and offset', async () => { + await getAllEvents(mockReq) + expect(authorisedRequestStub).to.have.been.calledWith( + mockReq, + `${config.apiRoot}/v3/event?limit=100000&offset=0` + ) + }) + }) - afterEach(() => { - this.clock.restore() - }) + context('getActiveEvents', () => { + let clock - it('should call search to get all active events today', () => { - expect(this.searchSpy).to.be.calledWith({ - req: stubRequest, - searchEntity: 'event', - requestBody: { - sortby: 'name:asc', - disabled_on: { - exists: false, - after: this.currentFormattedTime, - }, - }, - limit: 100000, - isAggregation: false, - }) - }) - }) + after(() => { + clock.restore() + }) - context( - 'and when asked for all active events at a point in time', - () => { - beforeEach(async () => { - const now = new Date() - this.createdOn = now.toISOString() - this.events = await this.repos.getActiveEvents( - stubRequest, - this.createdOn - ) - }) + it('should fetch active events at the current point in time when no date supplied', async () => { + const now = new Date() + clock = sinon.useFakeTimers({ + now: now, + shouldAdvanceTime: false, + }) + const mockedResults = [{ id: '1', name: 'Active Event' }] + searchStub.resolves({ results: mockedResults }) + const result = await getActiveEvents(mockReq) + expect(searchStub).to.have.been.calledWith({ + req: mockReq, + searchEntity: 'event', + requestBody: { + sortby: 'name:asc', + disabled_on: { + after: now.toISOString(), + exists: false, + }, + }, + limit: 100000, + isAggregation: false, + }) + expect(result).to.deep.equal(mockedResults) + }) - it('should call search to get all active events on the specified date', () => { - expect(this.searchSpy).to.be.calledWith({ - req: stubRequest, - searchEntity: 'event', - requestBody: { - sortby: 'name:asc', - disabled_on: { - exists: false, - after: this.createdOn, - }, - }, - limit: 100000, - isAggregation: false, - }) - }) - } - ) - } - ) + it('should fetch active events at the specified point in time', async () => { + const specificDate = new Date('2024-12-10T12:00:00Z').toISOString() + const mockedResults = [{ id: '1', name: 'Active Event' }] + searchStub.resolves({ results: mockedResults }) + const result = await getActiveEvents(mockReq, specificDate) + expect(searchStub).to.have.been.calledWith({ + req: mockReq, + searchEntity: 'event', + requestBody: { + sortby: 'name:asc', + disabled_on: { + after: specificDate, + exists: false, + }, + }, + limit: 100000, + isAggregation: false, + }) + expect(result).to.deep.equal(mockedResults) + }) }) })