diff --git a/client/.eslintrc.json b/client/.eslintrc.json index 634ed889e..209575843 100644 --- a/client/.eslintrc.json +++ b/client/.eslintrc.json @@ -5,7 +5,7 @@ "es6": true, "browser": true }, - "plugins": ["prettier"], + "plugins": ["prettier", "vitest"], "extends": ["eslint:recommended", "plugin:prettier/recommended"], "rules": { "no-console": "error", diff --git a/client/package.json b/client/package.json index 46bd4197b..1b57add62 100644 --- a/client/package.json +++ b/client/package.json @@ -45,6 +45,7 @@ "@vitest/coverage-v8": "^1.2.2", "@vue/eslint-config-typescript": "^11.0.3", "@vue/test-utils": "2.2.1", + "eslint-plugin-vitest": "0.3.22", "eslint-plugin-vue": "9.7.0", "jsdom": "^21.1.0", "sass": "^1.41.1", diff --git a/client/tests/unit/.eslintrc.json b/client/tests/unit/.eslintrc.json index b8e8b900a..df3808883 100644 --- a/client/tests/unit/.eslintrc.json +++ b/client/tests/unit/.eslintrc.json @@ -1,26 +1,21 @@ { "env": { - "jest": true, "browser": true }, - "plugins": ["jest"], + "plugins": ["vitest"], "rules": { "no-console": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/require-await": "off", "@typescript-eslint/no-floating-promises": "off", - "jest/consistent-test-it": ["error", { "fn": "it" }], - "jest/expect-expect": "warn", - "jest/no-duplicate-hooks": "error", - "jest/no-focused-tests": "error", - "jest/no-identical-title": "error", - "jest/no-if": "error", - "jest/no-expect-resolves": "error", - "jest/no-export": "error", - "jest/no-standalone-expect": "error", - "jest/no-truthy-falsy": "error", - "jest/prefer-spy-on": "error", - "jest/require-top-level-describe": "warn" + "vitest/consistent-test-it": ["error", { "fn": "it" }], + "vitest/expect-expect": "warn", + "vitest/no-conditional-in-test": "error", + "vitest/no-duplicate-hooks": "error", + "vitest/no-focused-tests": "error", + "vitest/no-identical-title": "error", + "vitest/prefer-spy-on": "error", + "vitest/require-top-level-describe": "warn" } } diff --git a/client/tests/unit/Room.spec.js b/client/tests/unit/Room.spec.js index 3fb7e1197..5bc0a6998 100644 --- a/client/tests/unit/Room.spec.js +++ b/client/tests/unit/Room.spec.js @@ -99,7 +99,7 @@ describe.skip("Room UI spec", () => { it("should render timestamps as 00:00 if there is nothing playing", () => { store.state.room.currentSource = {}; - jest.advanceTimersByTime(1000); + vi.advanceTimersByTime(1000); const timestamp = wrapper.find(".video-controls .timestamp"); expect(timestamp.exists()).toBe(true); expect(timestamp.text()).toEqual("00:00"); @@ -111,7 +111,7 @@ describe.skip("Room UI spec", () => { it("should render timestamps if there is something playing", () => { store.state.room.currentSource = { service: "youtube", id: "I3O9J02G67I", length: 10 }; store.state.room.playbackPosition = 3; - jest.advanceTimersByTime(1000); + vi.advanceTimersByTime(1000); const timestamp = wrapper.find(".video-controls .timestamp"); expect(timestamp.exists()).toBe(true); expect(timestamp.text()).toEqual("00:03"); diff --git a/package.json b/package.json index 4384cfa7d..b65bb5fcf 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,6 @@ "winston": "^3.10.0" }, "devDependencies": { - "@jest/globals": "^29.5.0", - "@types/jest": "29.5.0", "@types/lodash": "^4.14.170", "@types/node": "^16.11.7", "@types/uuid": "^3.4.0", @@ -58,14 +56,11 @@ "eslint": "7.32.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-jest": "23.13.2", "eslint-plugin-prettier": "^4.0.0", "faker": "^5.5.3", - "jest": "29.5.0", "prettier": "^2.5.1", "start-server-and-test": "^1.12.3", "supertest": "6.3.3", - "ts-jest": "29.1.1", "ts-node": "^10.9.1" } } \ No newline at end of file diff --git a/packages/ott-vis-datasource/tsconfig.json b/packages/ott-vis-datasource/tsconfig.json index 61f2c18a4..3b79176e5 100644 --- a/packages/ott-vis-datasource/tsconfig.json +++ b/packages/ott-vis-datasource/tsconfig.json @@ -1,3 +1,7 @@ { - "extends": "./.config/tsconfig.json" + "extends": "./.config/tsconfig.json", + "compilerOptions": { + "strict": true, + "typeRoots": ["../../node_modules/@types"] + } } diff --git a/packages/ott-vis/tsconfig.json b/packages/ott-vis/tsconfig.json index 54f12e692..3b79176e5 100644 --- a/packages/ott-vis/tsconfig.json +++ b/packages/ott-vis/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "./.config/tsconfig.json", "compilerOptions": { - "strict": true + "strict": true, + "typeRoots": ["../../node_modules/@types"] } } diff --git a/server/babel.config.cjs b/server/babel.config.cjs deleted file mode 100644 index 5543312b2..000000000 --- a/server/babel.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - env: { - test: { - plugins: ["@babel/plugin-transform-modules-commonjs"], - }, - }, -}; diff --git a/server/package.json b/server/package.json index 3c0f0b001..9459c103f 100644 --- a/server/package.json +++ b/server/package.json @@ -11,7 +11,7 @@ "build": "tsc", "lint": "tsc --noEmit && eslint --fix .", "lint-ci": "tsc --noEmit && eslint .", - "test": "jest --config ./tests/unit/jest.config.js -experimental-vm-modules --runInBand --detectOpenHandles --forceExit --coverage" + "test": "vitest run --coverage" }, "dependencies": { "@divine/synchronization": "^1.2.1", @@ -48,8 +48,6 @@ "ws": "^7.4.6" }, "devDependencies": { - "@babel/core": "^7.20.2", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", "@types/convict": "^6.1.1", "@types/express": "^4.17.11", "@types/express-session": "^1.17.3", @@ -60,10 +58,10 @@ "@types/sequelize": "^4.28.9", "@types/supertest": "^2.0.11", "@types/ws": "^7.4.4", - "babel-jest": "29.5.0", - "jest-watch-typeahead": "^2.2.1", + "eslint-plugin-vitest": "0.3.22", "nodemon": "^2.0.4", "redis-mock": "^0.56.3", - "sqlite3": "5.1.5" + "sqlite3": "5.1.5", + "vitest": "^1.2.2" } } \ No newline at end of file diff --git a/server/tests/unit/.eslintrc.json b/server/tests/unit/.eslintrc.json index b8e8b900a..7ec27009e 100644 --- a/server/tests/unit/.eslintrc.json +++ b/server/tests/unit/.eslintrc.json @@ -1,26 +1,21 @@ { "env": { - "jest": true, - "browser": true }, - "plugins": ["jest"], + "plugins": ["vitest"], "rules": { "no-console": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/require-await": "off", "@typescript-eslint/no-floating-promises": "off", - "jest/consistent-test-it": ["error", { "fn": "it" }], - "jest/expect-expect": "warn", - "jest/no-duplicate-hooks": "error", - "jest/no-focused-tests": "error", - "jest/no-identical-title": "error", - "jest/no-if": "error", - "jest/no-expect-resolves": "error", - "jest/no-export": "error", - "jest/no-standalone-expect": "error", - "jest/no-truthy-falsy": "error", - "jest/prefer-spy-on": "error", - "jest/require-top-level-describe": "warn" + "vitest/consistent-test-it": ["error", { "fn": "it" }], + "vitest/expect-expect": "warn", + "vitest/no-conditional-in-test": "error", + "vitest/no-duplicate-hooks": "error", + "vitest/no-focused-tests": "error", + "vitest/no-identical-title": "error", + "vitest/no-standalone-expect": "error", + "vitest/prefer-spy-on": "error", + "vitest/require-top-level-describe": "warn" } } diff --git a/server/tests/unit/api/accountrecovery.spec.ts b/server/tests/unit/api/accountrecovery.spec.ts index afd753331..41fb1fe3e 100644 --- a/server/tests/unit/api/accountrecovery.spec.ts +++ b/server/tests/unit/api/accountrecovery.spec.ts @@ -1,7 +1,19 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import request from "supertest"; import { main } from "../../../app"; import usermanager from "../../../usermanager"; import { User as UserModel } from "../../../models"; +import { User } from "../../../models/user"; import { MockMailer } from "server/mailer"; import { conf } from "../../../ott-config"; import { redisClient } from "../../../redisclient"; @@ -10,17 +22,19 @@ import { OttApiRequestAccountRecoveryVerify } from "common/models/rest-api"; describe("Account Recovery", () => { let token; let app; + let emailUser: User; + let noEmailUser: User; beforeAll(async () => { app = (await main()).app; - await usermanager.registerUser({ + emailUser = await usermanager.registerUser({ email: "email@localhost", username: "email user", password: "test1234", }); - await usermanager.registerUser({ + noEmailUser = await usermanager.registerUser({ email: null, username: "no email user", password: "test1234", @@ -40,7 +54,9 @@ describe("Account Recovery", () => { }); afterAll(async () => { - await UserModel.destroy({ where: {} }); + await emailUser.destroy(); + await noEmailUser.destroy(); + conf.set("mail.enabled", false); }); it.each([ diff --git a/server/tests/unit/api/announcement.spec.ts b/server/tests/unit/api/announcement.spec.ts index 6ee3a4aff..fab05319f 100644 --- a/server/tests/unit/api/announcement.spec.ts +++ b/server/tests/unit/api/announcement.spec.ts @@ -1,31 +1,43 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import request from "supertest"; import { main } from "../../../app"; import { setApiKey } from "../../../admin"; import { ANNOUNCEMENT_CHANNEL } from "../../../../common/constants"; import { redisClient } from "../../../redisclient"; -import tokens from "../../../auth/tokens"; +import tokens, { type SessionInfo } from "../../../auth/tokens"; +import type { AuthToken } from "../../../../common/models/types"; const TEST_API_KEY = "TESTAPIKEY"; describe("Announcements API", () => { let app; - let publishSpy; - let getSessionInfoSpy; - let validateSpy; + let publishSpy: MockInstance>; + let getSessionInfoSpy: MockInstance<[AuthToken], Promise>; + let validateSpy: MockInstance<[AuthToken], Promise>; beforeAll(async () => { setApiKey(TEST_API_KEY); - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: false, username: "test", }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); app = (await main()).app; }); beforeEach(() => { - publishSpy = jest.spyOn(redisClient, "publish").mockResolvedValue(1); + publishSpy = vi.spyOn(redisClient, "publish").mockResolvedValue(1); }); afterEach(() => { diff --git a/server/tests/unit/api/data.spec.ts b/server/tests/unit/api/data.spec.ts index f40797b5c..104433d0e 100644 --- a/server/tests/unit/api/data.spec.ts +++ b/server/tests/unit/api/data.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import request from "supertest"; import { main } from "../../../app"; import InfoExtract, { AddPreview } from "../../../infoextractor"; @@ -9,11 +20,11 @@ describe("Data API", () => { let validateSpy; beforeAll(async () => { - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: false, username: "test", }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); app = (await main()).app; }); @@ -23,9 +34,9 @@ describe("Data API", () => { }); it("GET /data/previewAdd", async () => { - let resolveQuerySpy = jest + let resolveQuerySpy = vi .spyOn(InfoExtract, "resolveVideoQuery") - .mockReturnValue(Promise.resolve(new AddPreview([], 0))); + .mockResolvedValue(new AddPreview([], 0)); await request(app) .get("/api/data/previewAdd") @@ -40,14 +51,9 @@ describe("Data API", () => { }); resolveQuerySpy.mockRestore(); - resolveQuerySpy = jest + resolveQuerySpy = vi .spyOn(InfoExtract, "resolveVideoQuery") - .mockImplementation( - () => - new Promise((resolve, reject) => - reject({ name: "UnsupportedServiceException", message: "error message" }) - ) - ); + .mockRejectedValue({ name: "UnsupportedServiceException", message: "error message" }); await request(app) .get("/api/data/previewAdd") @@ -62,7 +68,7 @@ describe("Data API", () => { }); resolveQuerySpy.mockRestore(); - resolveQuerySpy = jest.spyOn(InfoExtract, "resolveVideoQuery").mockImplementation( + resolveQuerySpy = vi.spyOn(InfoExtract, "resolveVideoQuery").mockImplementation( () => new Promise((resolve, reject) => reject({ @@ -85,7 +91,7 @@ describe("Data API", () => { }); resolveQuerySpy.mockRestore(); - resolveQuerySpy = jest + resolveQuerySpy = vi .spyOn(InfoExtract, "resolveVideoQuery") .mockImplementation( () => diff --git a/server/tests/unit/api/room.spec.ts b/server/tests/unit/api/room.spec.ts index fd2827919..5d1536e6e 100644 --- a/server/tests/unit/api/room.spec.ts +++ b/server/tests/unit/api/room.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import _ from "lodash"; import { QueueMode, Visibility } from "../../../../common/models/types"; import request from "supertest"; @@ -74,14 +85,14 @@ describe("Room API", () => { }); describe("GET /room/:name", () => { - let getSessionInfoSpy: jest.SpyInstance; - let validateSpy: jest.SpyInstance; + let getSessionInfoSpy: MockInstance; + let validateSpy: MockInstance; beforeAll(async () => { - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: false, username: "test", }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); }); afterAll(() => { @@ -137,14 +148,15 @@ describe("Room API", () => { }); describe("POST /room/create", () => { - let getSessionInfoSpy: jest.SpyInstance; - let validateSpy: jest.SpyInstance; + let getSessionInfoSpy: MockInstance; + let validateSpy: MockInstance; + beforeAll(async () => { - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: false, username: "test", }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); }); afterAll(() => { @@ -160,7 +172,6 @@ describe("Room API", () => { throw e; } } - await UserModel.destroy({ where: {} }); }); it.each([Visibility.Public, Visibility.Unlisted])( @@ -267,11 +278,11 @@ describe("Room API", () => { it("should create permanent room with owner", async () => { const user = await usermanager.registerUser({ - email: "forced@localhost", + email: "owner@localhost", username: "owner", password: "password1234", }); - jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: true, user_id: user.id, }); @@ -290,6 +301,7 @@ describe("Room API", () => { }); await roommanager.unloadRoom("testowner"); await RoomModel.destroy({ where: { name: "testowner" } }); + await user.destroy(); }); const requests: [string, OttApiRequestRoomCreate | undefined][] = [ @@ -319,15 +331,15 @@ describe("Room API", () => { }); describe("PATCH /api/room/:name", () => { - let getSessionInfoSpy: jest.SpyInstance; - let validateSpy: jest.SpyInstance; + let getSessionInfoSpy: MockInstance; + let validateSpy: MockInstance; beforeAll(async () => { - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ isLoggedIn: false, username: "test", }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); await roommanager.createRoom({ name: "foo", diff --git a/server/tests/unit/api/user.spec.ts b/server/tests/unit/api/user.spec.ts index 65a172cd5..8653babc4 100644 --- a/server/tests/unit/api/user.spec.ts +++ b/server/tests/unit/api/user.spec.ts @@ -1,33 +1,48 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, + Mock, +} from "vitest"; import request from "supertest"; import { main } from "../../../app"; import usermanager from "../../../usermanager"; import { User as UserModel } from "../../../models"; import { conf } from "../../../ott-config"; +import { User } from "../../../models/user"; +import { AuthToken } from "common/models/types"; describe("User API", () => { let token; let app; + let forcedUser: User; + let testUser: User; + let socialUser: User; beforeAll(async () => { app = (await main()).app; }); beforeEach(async () => { - await UserModel.destroy({ where: {} }); - - await usermanager.registerUser({ + forcedUser = await usermanager.registerUser({ email: "forced@localhost", username: "forced test user", password: "test1234", }); - await usermanager.registerUser({ + testUser = await usermanager.registerUser({ email: "test@localhost", username: "test user", password: "test1234", }); - await usermanager.registerUserSocial({ + socialUser = await usermanager.registerUserSocial({ username: "social user", discordId: 1234567890, }); @@ -36,8 +51,10 @@ describe("User API", () => { token = resp.body.token; }); - afterAll(async () => { - await UserModel.destroy({ where: {} }); + afterEach(async () => { + await forcedUser.destroy(); + await testUser.destroy(); + await socialUser.destroy(); }); describe("GET /user", () => { @@ -80,7 +97,7 @@ describe("User API", () => { let onUserModifiedSpy; beforeAll(() => { - onUserModifiedSpy = jest.fn(); + onUserModifiedSpy = vi.fn(); usermanager.on("userModified", onUserModifiedSpy); }); @@ -173,7 +190,7 @@ describe("User API", () => { let onUserLogInSpy; beforeAll(() => { - onUserLogInSpy = jest.fn(); + onUserLogInSpy = vi.fn(); usermanager.on("login", onUserLogInSpy); }); @@ -238,7 +255,7 @@ describe("User API", () => { let onUserLogOutSpy; beforeAll(() => { - onUserLogOutSpy = jest.fn(); + onUserLogOutSpy = vi.fn(); usermanager.on("logout", onUserLogOutSpy); }); @@ -280,10 +297,13 @@ describe("User API", () => { }); describe("POST /user/register", () => { - let onUserLogInSpy; + let onUserLogInSpy: Mock<[User, AuthToken]>; + let registeredUsers: User[] = []; beforeAll(() => { - onUserLogInSpy = jest.fn(); + onUserLogInSpy = vi.fn().mockImplementation((user, token) => { + registeredUsers.push(user); + }); usermanager.on("login", onUserLogInSpy); }); @@ -292,6 +312,12 @@ describe("User API", () => { conf.set("users.enable_registration", true); }); + afterEach(async () => { + for (const user of registeredUsers.splice(0)) { + await user.destroy(); + } + }); + afterAll(() => { onUserLogInSpy.mockRestore(); usermanager.off("login", onUserLogInSpy); diff --git a/server/tests/unit/clientmanager.spec.ts b/server/tests/unit/clientmanager.spec.ts index 5f0f7a793..1fff37104 100644 --- a/server/tests/unit/clientmanager.spec.ts +++ b/server/tests/unit/clientmanager.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import clientmanager, { parseWebsocketConnectionUrl } from "../../clientmanager"; import { BalancerConnection, @@ -18,8 +19,8 @@ import { loadConfigFile, conf } from "../../ott-config"; import { M2BInit } from "server/generated"; class TestClient extends Client { - sendRawMock = jest.fn(); - kickMock = jest.fn(); + sendRawMock = vi.fn(); + kickMock = vi.fn(); sendRaw(msg: string): void { this.sendRawMock(msg); @@ -32,7 +33,7 @@ class TestClient extends Client { } class BalancerConnectionMock extends BalancerConnection { - sendMock = jest.fn(); + sendMock = vi.fn<[MsgM2B], void>(); constructor() { super(); diff --git a/server/tests/unit/infoextractor.spec.ts b/server/tests/unit/infoextractor.spec.ts index e136a7090..ad3181d3f 100644 --- a/server/tests/unit/infoextractor.spec.ts +++ b/server/tests/unit/infoextractor.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import InfoExtractor, { initExtractor } from "../../infoextractor"; import storage from "../../storage"; import { getMimeType } from "../../mime"; @@ -8,7 +19,7 @@ import { buildClients, redisClient } from "../../redisclient"; import _ from "lodash"; import { loadModels } from "../../models"; import { loadConfigFile, conf } from "../../ott-config"; -import { Video, VideoService } from "../../../common/models/video"; +import { Video, VideoMetadata, VideoService } from "../../../common/models/video"; class TestAdapter extends ServiceAdapter { get serviceId(): VideoService { @@ -78,13 +89,13 @@ describe("InfoExtractor", () => { it("should use cached search results", async () => { await redisClient.set("search:fakeservice:asdf", JSON.stringify([vid])); let adapter = new TestAdapter(); - let getAdapterSpy = jest + let getAdapterSpy = vi .spyOn(InfoExtractor, "getServiceAdapter") .mockReturnValue(adapter); - let getCacheSpy = jest + let getCacheSpy = vi .spyOn(InfoExtractor, "getCachedSearchResults") .mockResolvedValue([vid]); - let getManyVideoInfoSpy = jest + let getManyVideoInfoSpy = vi .spyOn(InfoExtractor, "getManyVideoInfo") .mockResolvedValue([vid]); let results = await InfoExtractor.searchVideos(adapter.serviceId, "asdf"); @@ -102,19 +113,19 @@ describe("InfoExtractor", () => { it("should cache fresh search results", async () => { let adapter = new TestAdapter(); - let getAdapterSpy = jest + let getAdapterSpy = vi .spyOn(InfoExtractor, "getServiceAdapter") .mockReturnValue(adapter); - let getCacheSpy = jest + let getCacheSpy = vi .spyOn(InfoExtractor, "getCachedSearchResults") .mockResolvedValue([]); - let searchSpy = jest.spyOn(adapter, "searchVideos").mockResolvedValue([ + let searchSpy = vi.spyOn(adapter, "searchVideos").mockResolvedValue([ { service: "direct", id: "asdf1234", }, ]); - let getManyVideoInfoSpy = jest + let getManyVideoInfoSpy = vi .spyOn(InfoExtractor, "getManyVideoInfo") .mockResolvedValue([vid]); @@ -138,16 +149,29 @@ describe("InfoExtractor", () => { }); describe("getVideoInfo", () => { - let getAdapter; - let getCachedVideo; - let updateCache; - let adapterFetchVideoInfo; + let getAdapter: MockInstance<[string], ServiceAdapter>; + let getCachedVideo: MockInstance< + [VideoService, string], + Promise<[Video, (keyof VideoMetadata)[]]> + >; + let updateCache: MockInstance<[Video[] | Video], Promise>; + let adapterFetchVideoInfo: MockInstance; beforeAll(() => { let adapter = new TestAdapter(); - getAdapter = jest.spyOn(InfoExtractor, "getServiceAdapter").mockReturnValue(adapter); - getCachedVideo = jest.spyOn(InfoExtractor, "getCachedVideo").mockImplementation(); - updateCache = jest.spyOn(InfoExtractor, "updateCache").mockImplementation(); - adapterFetchVideoInfo = jest.spyOn(adapter, "fetchVideoInfo"); + getAdapter = vi.spyOn(InfoExtractor, "getServiceAdapter").mockReturnValue(adapter); + getCachedVideo = vi + .spyOn(InfoExtractor, "getCachedVideo") + .mockImplementation((service, id) => { + return Promise.resolve([ + { + service, + id, + }, + ["title", "description", "length", "thumbnail"], + ]); + }); + updateCache = vi.spyOn(InfoExtractor, "updateCache").mockResolvedValue(); + adapterFetchVideoInfo = vi.spyOn(adapter, "fetchVideoInfo"); }); afterEach(() => { updateCache.mockClear(); @@ -248,18 +272,31 @@ describe("InfoExtractor", () => { }); describe("getManyVideoInfo", () => { - let getAdapter; - let getCachedVideo; - let updateCache; - let adapterFetchManyVideoInfo; - let storageGetManyVideoInfo; + let getAdapter: MockInstance<[string], ServiceAdapter>; + let getCachedVideo: MockInstance< + [VideoService, string], + Promise<[Video, (keyof VideoMetadata)[]]> + >; + let updateCache: MockInstance<[Video[] | Video], Promise>; + let adapterFetchManyVideoInfo: MockInstance; + let storageGetManyVideoInfo: MockInstance; beforeAll(() => { let adapter = new TestAdapter(); - getAdapter = jest.spyOn(InfoExtractor, "getServiceAdapter").mockReturnValue(adapter); - getCachedVideo = jest.spyOn(InfoExtractor, "getCachedVideo").mockImplementation(); - updateCache = jest.spyOn(InfoExtractor, "updateCache").mockImplementation(); - adapterFetchManyVideoInfo = jest.spyOn(adapter, "fetchManyVideoInfo"); - storageGetManyVideoInfo = jest.spyOn(storage, "getManyVideoInfo").mockImplementation(); + getAdapter = vi.spyOn(InfoExtractor, "getServiceAdapter").mockReturnValue(adapter); + getCachedVideo = vi + .spyOn(InfoExtractor, "getCachedVideo") + .mockImplementation((service, id) => { + return Promise.resolve([ + { + service, + id, + }, + ["title", "description", "length", "thumbnail"], + ]); + }); + updateCache = vi.spyOn(InfoExtractor, "updateCache").mockResolvedValue(); + adapterFetchManyVideoInfo = vi.spyOn(adapter, "fetchManyVideoInfo"); + storageGetManyVideoInfo = vi.spyOn(storage, "getManyVideoInfo"); }); afterEach(() => { updateCache.mockClear(); @@ -308,7 +345,7 @@ describe("InfoExtractor", () => { vids.map(vid => _.pick(vid, "service", "id")) ); adapterFetchManyVideoInfo.mockResolvedValue(vids); - updateCache.mockImplementation(); + updateCache.mockResolvedValue(); expect( await InfoExtractor.getManyVideoInfo(vids.map(vid => _.pick(vid, "service", "id"))) ).toEqual(vids); @@ -319,7 +356,7 @@ describe("InfoExtractor", () => { it("should get some videos from cache, and the rest fetching from adapter", async () => { storageGetManyVideoInfo.mockResolvedValue([vids[0], _.pick(vids[1], "service", "id")]); adapterFetchManyVideoInfo.mockResolvedValue(vids); - updateCache.mockImplementation(); + updateCache.mockResolvedValue(); expect( await InfoExtractor.getManyVideoInfo(vids.map(vid => _.pick(vid, "service", "id"))) ).toEqual(vids); @@ -332,7 +369,7 @@ describe("InfoExtractor", () => { describe("InfoExtractor: Cache", () => { describe("getCachedVideo", () => { it("should get video from cache", async () => { - let getVideoInfoSpy = jest.spyOn(storage, "getVideoInfo").mockResolvedValue({ + let getVideoInfoSpy = vi.spyOn(storage, "getVideoInfo").mockResolvedValue({ service: "youtube", id: "94L1GMA2wjk4", title: "example", @@ -348,7 +385,7 @@ describe("InfoExtractor: Cache", () => { expect(storage.getVideoInfo).toBeCalledTimes(1); getVideoInfoSpy.mockReset(); - getVideoInfoSpy = jest.spyOn(storage, "getVideoInfo").mockResolvedValue({ + getVideoInfoSpy = vi.spyOn(storage, "getVideoInfo").mockResolvedValue({ service: "direct", id: "https://example.com/asdf.mp4", title: "asdf.mp4", @@ -366,7 +403,7 @@ describe("InfoExtractor: Cache", () => { expect(storage.getVideoInfo).toBeCalledTimes(1); getVideoInfoSpy.mockReset(); - jest.spyOn(storage, "getVideoInfo").mockResolvedValue({ + vi.spyOn(storage, "getVideoInfo").mockResolvedValue({ service: "direct", id: "https://example.com/asdf.mp4", title: "asdf.mp4", @@ -386,7 +423,7 @@ describe("InfoExtractor: Cache", () => { expect(storage.getVideoInfo).toBeCalledTimes(1); getVideoInfoSpy.mockReset(); - jest.spyOn(storage, "getVideoInfo").mockResolvedValue({ + vi.spyOn(storage, "getVideoInfo").mockResolvedValue({ service: "direct", id: "https://example.com/asdf", title: "asdf", @@ -404,10 +441,10 @@ describe("InfoExtractor: Cache", () => { let updateVideoInfoSpy; let updateManyVideoInfoSpy; beforeEach(() => { - updateVideoInfoSpy = jest.spyOn(storage, "updateVideoInfo").mockImplementation(); - updateManyVideoInfoSpy = jest + updateVideoInfoSpy = vi.spyOn(storage, "updateVideoInfo").mockResolvedValue(true); + updateManyVideoInfoSpy = vi .spyOn(storage, "updateManyVideoInfo") - .mockImplementation(); + .mockResolvedValue(true); }); afterAll(() => { diff --git a/server/tests/unit/jest.config.js b/server/tests/unit/jest.config.js deleted file mode 100644 index 4d143860a..000000000 --- a/server/tests/unit/jest.config.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - preset: "ts-jest", - testEnvironment: "node", - transform: { - "^.+\\.jsx?$": "babel-jest", - }, - rootDir: "../..", - testMatch: ["**/tests/unit/**/*.spec.(js|ts)|**/__tests__/*.(js|ts)"], - testPathIgnorePatterns: ["/node_modules/", "/dist/", "/coverage/", "/ts-out/"], - watchPlugins: ["jest-watch-typeahead/filename", "jest-watch-typeahead/testname"], - // collectCoverage: true, - coverageReporters: ["text-summary", "text", "json", "html"], - collectCoverageFrom: [ - "**/*.{js,ts}", - "!**/node_modules/**", - "!**/dist/**", - "!**/*.config.js", - "!**/*.eslintrc.js", - "!**/config/**", - "!**/migrations/**", - "!**/models/**", - "!**/seeders/**", - "!**/coverage/**", - "!**/tests/**", - "!**/src/**", - "!app.js", - ], - setupFilesAfterEnv: ["./tests/unit/jest.setup.redis-mock.js"], -}; diff --git a/server/tests/unit/jest.setup.redis-mock.js b/server/tests/unit/jest.setup.redis-mock.js index 31c8463d9..fa03bfd07 100644 --- a/server/tests/unit/jest.setup.redis-mock.js +++ b/server/tests/unit/jest.setup.redis-mock.js @@ -1,2 +1,7 @@ +import { vi } from "vitest"; import mockredis from "./redisV4Mock"; -jest.mock("redis", () => mockredis); +vi.mock("redis", () => { + return { + default: mockredis, + }; +}); diff --git a/server/tests/unit/room.spec.ts b/server/tests/unit/room.spec.ts index 31743ac73..085a74c50 100644 --- a/server/tests/unit/room.spec.ts +++ b/server/tests/unit/room.spec.ts @@ -1,7 +1,18 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import dayjs from "dayjs"; -import tokens from "../../auth/tokens"; +import tokens, { SessionInfo } from "../../auth/tokens"; import { RoomRequestType } from "../../../common/models/messages"; -import { BehaviorOption, QueueMode, Role } from "../../../common/models/types"; +import { AuthToken, BehaviorOption, QueueMode, Role } from "../../../common/models/types"; import { Room, RoomUser } from "../../room"; import infoextractor from "../../infoextractor"; import { Video, VideoId } from "../../../common/models/video"; @@ -12,17 +23,17 @@ import { loadModels } from "../../models"; import { buildClients } from "../../redisclient"; describe("Room", () => { - let getSessionInfoSpy: jest.SpyInstance; - let validateSpy: jest.SpyInstance; + let getSessionInfoSpy: MockInstance<[AuthToken], Promise>; + let validateSpy: MockInstance<[AuthToken], Promise>; beforeAll(async () => { loadModels(); await buildClients(); - getSessionInfoSpy = jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + getSessionInfoSpy = vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ username: "test", isLoggedIn: false, }); - validateSpy = jest.spyOn(tokens, "validate").mockResolvedValue(true); + validateSpy = vi.spyOn(tokens, "validate").mockResolvedValue(true); }); afterAll(() => { @@ -177,7 +188,7 @@ describe("Room", () => { }; it("should place the requested video in currentSource", async () => { - jest.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); + vi.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); await room.processUnauthorizedRequest( { type: RoomRequestType.PlayNowRequest, @@ -189,7 +200,7 @@ describe("Room", () => { }); it("should remove the video from the queue", async () => { - jest.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); + vi.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); room.currentSource = { service: "direct", id: "asdf123", @@ -209,7 +220,7 @@ describe("Room", () => { }); it("should push the currently playing video into the queue", async () => { - jest.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); + vi.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); room.currentSource = { service: "direct", id: "asdf123", @@ -233,7 +244,7 @@ describe("Room", () => { }); it("should reset playback position to 0", async () => { - jest.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); + vi.spyOn(infoextractor, "getVideoInfo").mockResolvedValue(videoToPlay); room.currentSource = { service: "direct", id: "asdf123", @@ -277,7 +288,7 @@ describe("Room", () => { { service: "direct", id: "video4" }, { service: "direct", id: "video5" }, ]); - shuffleSpy = jest.spyOn(_, "shuffle"); + shuffleSpy = vi.spyOn(_, "shuffle"); }); afterEach(() => { @@ -437,7 +448,7 @@ describe("Room", () => { }); it("should be able to get role in unowned room", async () => { - jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ username: "test", isLoggedIn: false, }); @@ -445,7 +456,7 @@ describe("Room", () => { const room = new Room({ name: "test" }); expect(await room.getRoleFromToken("fake")).toEqual(Role.UnregisteredUser); - jest.spyOn(tokens, "getSessionInfo").mockResolvedValue({ + vi.spyOn(tokens, "getSessionInfo").mockResolvedValue({ user_id: -1, isLoggedIn: true, }); diff --git a/server/tests/unit/roommanager.spec.ts b/server/tests/unit/roommanager.spec.ts index 39086401d..d86df1d09 100644 --- a/server/tests/unit/roommanager.spec.ts +++ b/server/tests/unit/roommanager.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, afterEach, vi } from "vitest"; import roommanager, { redisStateToState } from "../../roommanager"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -17,8 +18,7 @@ describe("Room manager", () => { await buildClients(); }); - beforeEach(async () => { - await DbRoom.destroy({ where: {} }); + afterEach(async () => { for (const room of roommanager.rooms) { await roommanager.unloadRoom(room.name); } @@ -27,41 +27,44 @@ describe("Room manager", () => { describe("creating a room", () => { it("should never save null to permissions or user role columns", async () => { - await roommanager.createRoom({ name: "test", isTemporary: false, title: "asdf1234" }); - const room = await DbRoom.findOne({ where: { name: "test" } }); + const roomName = "foo-76kdf943"; + await roommanager.createRoom({ name: roomName, isTemporary: false, title: "asdf1234" }); + const room = await DbRoom.findOne({ where: { name: roomName } }); expect(room).not.toBeNull(); expect(room?.permissions).not.toBeNull(); - // eslint-disable-next-line jest/no-if + expect(room?.permissions).toBeInstanceOf(Array); + // eslint-disable-next-line vitest/no-conditional-in-test if (Array.isArray(room?.permissions)) { let roles = room?.permissions.map(p => p[0]); expect(roles).not.toContain(Role.Administrator); expect(roles).not.toContain(Role.Owner); - } else { - throw new Error("permissions should be an array on a newly created room"); } expect(room?.["role-admin"]).toBeInstanceOf(Array); expect(room?.["role-mod"]).toBeInstanceOf(Array); expect(room?.["role-trusted"]).toBeInstanceOf(Array); + await room?.destroy(); }); it("should be able to load saved settings from database", async () => { + const roomName = "foo-a3b5e323"; await roommanager.createRoom({ - name: "test", + name: roomName, isTemporary: false, title: "asdf1234", description: "0987asdf", visibility: Visibility.Unlisted, queueMode: QueueMode.Vote, }); - const room = await DbRoom.findOne({ where: { name: "test" } }); + const room = await DbRoom.findOne({ where: { name: roomName } }); expect(room).not.toBeNull(); expect(room).toMatchObject({ - name: "test", + name: roomName, title: "asdf1234", description: "0987asdf", visibility: Visibility.Unlisted, queueMode: QueueMode.Vote, }); + await room?.destroy(); }); }); @@ -104,10 +107,7 @@ describe("Room manager", () => { }); it("should not load the room if it is not already loaded in memory", async () => { - const getRoomByNameSpy = jest - .spyOn(storage, "getRoomByName") - .mockImplementation() - .mockResolvedValue(null); + const getRoomByNameSpy = vi.spyOn(storage, "getRoomByName").mockResolvedValue(null); let result = await roommanager.getRoom("test", { mustAlreadyBeLoaded: true, }); diff --git a/server/tests/unit/services/dailymotion.spec.ts b/server/tests/unit/services/dailymotion.spec.ts index 82baad1a7..f6113345a 100644 --- a/server/tests/unit/services/dailymotion.spec.ts +++ b/server/tests/unit/services/dailymotion.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import DailyMotionAdapter from "../../../../server/services/dailymotion"; import { InvalidVideoIdException } from "../../../../server/exceptions"; @@ -49,7 +50,7 @@ describe("Dailymotion", () => { describe("fetchVideoInfo", () => { const adapter = new DailyMotionAdapter(); - const apiGet = jest.fn(); + const apiGet = vi.fn(); apiGet.mockReturnValue({ data: {} }); adapter.api.get = apiGet; const videoId = "jriwl35"; diff --git a/server/tests/unit/services/dash.spec.ts b/server/tests/unit/services/dash.spec.ts index f8a5b6325..5d2a56236 100644 --- a/server/tests/unit/services/dash.spec.ts +++ b/server/tests/unit/services/dash.spec.ts @@ -1,6 +1,7 @@ /** * Unit tests for DashVideoAdapter's MPD parsing methods */ +import { describe, it, expect, beforeEach, vi } from "vitest"; import DashVideoAdapter from "../../../services/dash"; import { UnsupportedVideoType } from "../../../exceptions"; import { parseIso8601Duration } from "../../../services/parsing/iso8601"; @@ -8,21 +9,21 @@ import axios from "axios"; import { DashMPD } from "@liveinstantly/dash-mpd-parser"; import URL from "url"; -jest.mock("axios"); -jest.mock("../../../services/parsing/iso8601"); -jest.mock("@liveinstantly/dash-mpd-parser"); +vi.mock("axios"); +vi.mock("../../../services/parsing/iso8601"); +vi.mock("@liveinstantly/dash-mpd-parser"); describe("DashVideoAdapter", () => { let adapter: DashVideoAdapter; - let mockAxiosGet: jest.Mock; - let mockParseIso8601Duration: jest.Mock; - let mockDashMPD: jest.Mock; + let mockAxiosGet; + let mockParseIso8601Duration; + let mockDashMPD; beforeEach(() => { adapter = new DashVideoAdapter(); - mockAxiosGet = axios.get as jest.Mock; - mockParseIso8601Duration = parseIso8601Duration as jest.Mock; - mockDashMPD = DashMPD as jest.Mock; + mockAxiosGet = axios.get; + mockParseIso8601Duration = parseIso8601Duration; + mockDashMPD = DashMPD; }); describe("handleMpd", () => { @@ -30,7 +31,7 @@ describe("DashVideoAdapter", () => { const mockMPDData = ``; const mockManifest = { MPD: { "@mediaPresentationDuration": "PT10S" } }; mockAxiosGet.mockResolvedValue({ data: mockMPDData }); - const mockParse = jest.fn(); + const mockParse = vi.fn(); mockDashMPD.mockImplementation(() => ({ parse: mockParse, getJSON: () => mockManifest, diff --git a/server/tests/unit/services/direct.spec.ts b/server/tests/unit/services/direct.spec.ts index 392087a12..1c4afff2c 100644 --- a/server/tests/unit/services/direct.spec.ts +++ b/server/tests/unit/services/direct.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import DirectVideoAdapter from "../../../services/direct"; import { FfprobeStrategy } from "../../../ffprobe"; import fs from "fs"; diff --git a/server/tests/unit/services/googledrive.spec.ts b/server/tests/unit/services/googledrive.spec.ts index 301def014..a64cc96e1 100644 --- a/server/tests/unit/services/googledrive.spec.ts +++ b/server/tests/unit/services/googledrive.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import GoogleDriveAdapter from "../../../../server/services/googledrive"; describe("Google Drive", () => { @@ -41,9 +42,9 @@ describe("Google Drive", () => { describe("fetchVideoInfo", () => { const adapter = new GoogleDriveAdapter(""); - jest.spyOn(adapter.api, "get"); + vi.spyOn(adapter.api, "get"); const videoId = "08ahsdlk0218"; - const apiGet = jest.fn().mockResolvedValue({ + const apiGet = vi.fn().mockResolvedValue({ data: { id: videoId, name: "Test video", @@ -79,13 +80,13 @@ describe("Google Drive", () => { describe("resolveURL", () => { const adapter = new GoogleDriveAdapter(""); - jest.spyOn(adapter.api, "get"); + vi.spyOn(adapter.api, "get"); it("Resolves URLs to single videos", async () => { const url = "https://drive.google.com/file/d/0ashda098sd892oihas/view?usp=sharing"; const videoId = "0ashda098sd892oihas"; - const apiGet = jest.fn().mockResolvedValue({ + const apiGet = vi.fn().mockResolvedValue({ data: { id: videoId, name: "Test video", @@ -113,7 +114,7 @@ describe("Google Drive", () => { it("Resolves a folder URL to a list of videos", async () => { const folderId = "bnas098dh9asund982hlkahsd9"; const url = `https://drive.google.com/drive/folders/${folderId}?usp=sharing`; - const apiGet = jest.fn().mockResolvedValue({ + const apiGet = vi.fn().mockResolvedValue({ data: { files: [ { diff --git a/server/tests/unit/services/parsing/iso8601.spec.ts b/server/tests/unit/services/parsing/iso8601.spec.ts index 4aef01d35..83d186708 100644 --- a/server/tests/unit/services/parsing/iso8601.spec.ts +++ b/server/tests/unit/services/parsing/iso8601.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect } from "vitest"; import { parseIso8601Duration } from "../../../../services/parsing/iso8601"; describe("parse iso8601 duration", () => { diff --git a/server/tests/unit/services/peertube.spec.ts b/server/tests/unit/services/peertube.spec.ts index 537ca033f..395c96a80 100644 --- a/server/tests/unit/services/peertube.spec.ts +++ b/server/tests/unit/services/peertube.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import PeertubeAdapter from "../../../services/peertube"; import fs from "fs"; import { InvalidVideoIdException } from "../../../exceptions"; @@ -15,7 +26,7 @@ const FIXTURE_DIRECTORY = "./tests/unit/fixtures/services/peertube"; describe("Peertube", () => { const adapter = new PeertubeAdapter(); const FIXTURES: Map = new Map(); - let apiGetMock: jest.SpyInstance; + let apiGetMock: MockInstance; beforeAll(async () => { await adapter.initialize(); @@ -27,7 +38,7 @@ describe("Peertube", () => { ); } - apiGetMock = jest.spyOn(adapter.api, "get").mockImplementation(async (url: string) => { + apiGetMock = vi.spyOn(adapter.api, "get").mockImplementation(async (url: string) => { const videoid = adapter.getVideoId(url); const [host, id] = videoid.split(":"); let fixtureText = FIXTURES.get(id); diff --git a/server/tests/unit/services/plutotv.spec.ts b/server/tests/unit/services/plutotv.spec.ts index cbcbad957..d4c9c38e4 100644 --- a/server/tests/unit/services/plutotv.spec.ts +++ b/server/tests/unit/services/plutotv.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import PlutoAdapter, { PlutoBootResponse, type PlutoParsedIds } from "../../../services/pluto"; import { AxiosResponse } from "axios"; import fs from "fs"; @@ -96,10 +107,10 @@ describe("Pluto TV", () => { describe("resolveUrl", () => { const adapter = new PlutoAdapter(); - let apiGetSpy: jest.SpyInstance; + let apiGetSpy: MockInstance; beforeAll(() => { - apiGetSpy = jest.spyOn(adapter.api, "get").mockImplementation(mockPlutoBoot); + apiGetSpy = vi.spyOn(adapter.api, "get").mockImplementation(mockPlutoBoot); }); afterEach(() => { @@ -146,10 +157,10 @@ describe("Pluto TV", () => { describe("fetchManyVideoInfo", () => { const adapter = new PlutoAdapter(); - let apiGetSpy: jest.SpyInstance; + let apiGetSpy: MockInstance; beforeAll(() => { - apiGetSpy = jest.spyOn(adapter.api, "get").mockImplementation(mockPlutoBoot); + apiGetSpy = vi.spyOn(adapter.api, "get").mockImplementation(mockPlutoBoot); }); afterEach(() => { diff --git a/server/tests/unit/services/reddit.spec.ts b/server/tests/unit/services/reddit.spec.ts index 9ae6a56a4..e843e158f 100644 --- a/server/tests/unit/services/reddit.spec.ts +++ b/server/tests/unit/services/reddit.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import RedditAdapter, { RedditListableThing, RedditListing, @@ -1380,7 +1381,7 @@ describe("Reddit", () => { const adapter = new RedditAdapter(); it("should get video urls", async () => { - jest.spyOn(adapter.api, "get").mockResolvedValue({ data: subredditListResponse }); + vi.spyOn(adapter.api, "get").mockResolvedValue({ data: subredditListResponse }); const videos = await adapter.resolveURL("https://reddit.com/r/youtubehaiku"); diff --git a/server/tests/unit/services/tubi.spec.ts b/server/tests/unit/services/tubi.spec.ts index 778edb1d9..b959768f2 100644 --- a/server/tests/unit/services/tubi.spec.ts +++ b/server/tests/unit/services/tubi.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import TubiAdapter from "../../../services/tubi"; import fs from "fs"; import { AxiosRequestHeaders, AxiosResponse } from "axios"; @@ -30,7 +41,7 @@ const FIXTURE_DIRECTORY = "./tests/unit/fixtures/services/tubi"; describe("Tubi TV", () => { const adapter = new TubiAdapter(); const FIXTURES: Map = new Map(); - let apiGetMock: jest.SpyInstance; + let apiGetMock: MockInstance; beforeAll(() => { for (let file of fs.readdirSync(FIXTURE_DIRECTORY)) { @@ -40,7 +51,7 @@ describe("Tubi TV", () => { ); } - apiGetMock = jest.spyOn(adapter.api, "get").mockImplementation(async (url: string) => { + apiGetMock = vi.spyOn(adapter.api, "get").mockImplementation(async (url: string) => { const id = adapter.isCollectionURL(url) ? new URL(url).pathname.split("/")[2] : adapter.getVideoId(url); diff --git a/server/tests/unit/services/vimeo.spec.ts b/server/tests/unit/services/vimeo.spec.ts index 1df96b5f8..048581ee4 100644 --- a/server/tests/unit/services/vimeo.spec.ts +++ b/server/tests/unit/services/vimeo.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import VimeoAdapter from "../../../services/vimeo"; import { InvalidVideoIdException } from "../../../exceptions"; @@ -36,7 +37,7 @@ describe("Vimeo", () => { describe("fetchVideoInfo", () => { const adapter = new VimeoAdapter(); - const apiGet = jest.fn(); + const apiGet = vi.fn(); apiGet.mockReturnValue({ data: {} }); adapter.api.get = apiGet; const videoId = "283918572"; diff --git a/server/tests/unit/services/youtube.spec.ts b/server/tests/unit/services/youtube.spec.ts index b9eeec1f6..f1b8e347f 100644 --- a/server/tests/unit/services/youtube.spec.ts +++ b/server/tests/unit/services/youtube.spec.ts @@ -1,3 +1,14 @@ +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + afterEach, + vi, + MockInstance, +} from "vitest"; import YouTubeAdapter, { YoutubeErrorResponse, YoutubeApiVideoListResponse, @@ -153,11 +164,11 @@ describe("Youtube", () => { }); describe("fetchVideoInfo", () => { - let apiGet: jest.SpyInstance; + let apiGet: MockInstance; const videoId = "BTZ5KVRUy1Q"; beforeAll(() => { - apiGet = jest.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); + apiGet = vi.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); }); beforeEach(() => { @@ -179,10 +190,10 @@ describe("Youtube", () => { }); describe("fetchManyVideoInfo", () => { - let apiGet: jest.SpyInstance; + let apiGet: MockInstance; beforeAll(() => { - apiGet = jest.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); + apiGet = vi.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); }); beforeEach(() => { @@ -225,10 +236,10 @@ describe("Youtube", () => { }); describe("resolveURL", () => { - let apiGet: jest.SpyInstance; + let apiGet: MockInstance; beforeAll(() => { - apiGet = jest.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); + apiGet = vi.spyOn(adapter.api, "get").mockImplementation(mockYoutubeApi); }); beforeEach(() => { @@ -260,9 +271,9 @@ describe("Youtube", () => { x.replace("%s", "zgxj_0xPleg").replace("%p", "PLABqEYq6H3vpCmsmyUnHnfMOeAnjBdSNm") ) )("Resolves single video URL with playlist, with video in the playlist: %s", async link => { - const fetchSpy = jest.spyOn(adapter, "fetchVideoWithPlaylist"); - const fetchVideo = jest.spyOn(adapter, "fetchVideoInfo"); - const fetchPlaylist = jest.spyOn(adapter, "fetchPlaylistVideos"); + const fetchSpy = vi.spyOn(adapter, "fetchVideoWithPlaylist"); + const fetchVideo = vi.spyOn(adapter, "fetchVideoInfo"); + const fetchPlaylist = vi.spyOn(adapter, "fetchPlaylistVideos"); const videos = await adapter.resolveURL(link); expect(fetchSpy).toHaveBeenCalledTimes(1); @@ -301,9 +312,9 @@ describe("Youtube", () => { )( "Resolves single video URL with playlist, with video NOT in the playlist: %s", async link => { - const fetchSpy = jest.spyOn(adapter, "fetchVideoWithPlaylist"); - const fetchVideo = jest.spyOn(adapter, "fetchVideoInfo"); - const fetchPlaylist = jest.spyOn(adapter, "fetchPlaylistVideos"); + const fetchSpy = vi.spyOn(adapter, "fetchVideoWithPlaylist"); + const fetchVideo = vi.spyOn(adapter, "fetchVideoInfo"); + const fetchPlaylist = vi.spyOn(adapter, "fetchPlaylistVideos"); const videos = await adapter.resolveURL(link); expect(fetchSpy).toHaveBeenCalledTimes(1); @@ -361,8 +372,8 @@ describe("Youtube", () => { it.each(["LL", "WL"].map(p => `https://youtube.com/watch?v=BTZ5KVRUy1Q&list=${p}`))( "Ignores the WL and LL private playlists", async link => { - const fetchVideoWithPlaylist = jest.spyOn(adapter, "fetchVideoWithPlaylist"); - const fetchVideo = jest.spyOn(adapter, "fetchVideoInfo"); + const fetchVideoWithPlaylist = vi.spyOn(adapter, "fetchVideoWithPlaylist"); + const fetchVideo = vi.spyOn(adapter, "fetchVideoInfo"); const videos: Video[] = await adapter.resolveURL(link); expect(videos).toHaveLength(1); expect(videos[0]).toEqual({ @@ -382,9 +393,9 @@ describe("Youtube", () => { ); it("Resolves playlist", async () => { - const fetchVideoWithPlaylist = jest.spyOn(adapter, "fetchVideoWithPlaylist"); - const fetchVideo = jest.spyOn(adapter, "fetchVideoInfo"); - const fetchPlaylist = jest.spyOn(adapter, "fetchPlaylistVideos"); + const fetchVideoWithPlaylist = vi.spyOn(adapter, "fetchVideoWithPlaylist"); + const fetchVideo = vi.spyOn(adapter, "fetchVideoInfo"); + const fetchPlaylist = vi.spyOn(adapter, "fetchPlaylistVideos"); const videos = await adapter.resolveURL( "https://youtube.com/playlist?list=PLABqEYq6H3vpCmsmyUnHnfMOeAnjBdSNm" @@ -452,7 +463,7 @@ describe("Youtube", () => { describe("searchVideos", () => { const adapter = new YouTubeAdapter("", redisClient); - const apiGet = jest.spyOn(adapter.api, "get"); + const apiGet = vi.spyOn(adapter.api, "get"); beforeEach(() => { apiGet.mockClear(); @@ -488,7 +499,7 @@ describe("Youtube", () => { describe("videoApiRequest", () => { const adapter = new YouTubeAdapter("", redisClient); - const apiGet = jest.spyOn(adapter.api, "get"); + const apiGet = vi.spyOn(adapter.api, "get"); const outOfQuotaResponse = { isAxiosError: true, response: { @@ -503,7 +514,7 @@ describe("Youtube", () => { it("should use the fallback when out of quota, and onlyProperties contains length", async () => { apiGet.mockRejectedValue(outOfQuotaResponse); - const fallbackSpy = jest.spyOn(adapter, "getVideoLengthFallback").mockResolvedValue(10); + const fallbackSpy = vi.spyOn(adapter, "getVideoLengthFallback").mockResolvedValue(10); const videos = await adapter.videoApiRequest("BTZ5KVRUy1Q", ["length"]); expect(videos[0]).toEqual({ service: "youtube", @@ -517,7 +528,7 @@ describe("Youtube", () => { it("should not use the fallback when out of quota, and onlyProperties does NOT contain length", async () => { apiGet.mockRejectedValue(outOfQuotaResponse); - const fallbackSpy = jest.spyOn(adapter, "getVideoLengthFallback").mockResolvedValue(10); + const fallbackSpy = vi.spyOn(adapter, "getVideoLengthFallback").mockResolvedValue(10); expect(adapter.videoApiRequest("BTZ5KVRUy1Q", ["title"])).rejects.toThrow( new OutOfQuotaException("youtube") ); diff --git a/server/tests/unit/storage.spec.ts b/server/tests/unit/storage.spec.ts index 24eba99ef..3f9a761d0 100644 --- a/server/tests/unit/storage.spec.ts +++ b/server/tests/unit/storage.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterEach } from "vitest"; import _ from "lodash"; import { CachedVideo, Room as DbRoom, User, loadModels } from "../../models"; import storage from "../../storage"; @@ -14,8 +15,11 @@ describe("Storage: Room Spec", () => { await buildClients(); }); - beforeEach(async () => { - await DbRoom.destroy({ where: {} }); + afterEach(async () => { + await DbRoom.destroy({ where: { name: "example" } }); + await DbRoom.destroy({ where: { name: "Example" } }); + await DbRoom.destroy({ where: { name: "capitalizedexampleroom" } }); + await DbRoom.destroy({ where: { name: "CapitalizedExampleRoom" } }); }); it("roomToDb and roomToDbPartial should return the same object", () => { @@ -229,6 +233,7 @@ describe("Storage: Room Spec", () => { describe("Storage: CachedVideos Spec", () => { afterEach(async () => { + // This is isolation safe because this is the only file to use the CachedVideo table await CachedVideo.destroy({ where: {} }); }); @@ -397,10 +402,12 @@ describe("Storage: CachedVideos Spec", () => { describe("Storage: CachedVideos: bulk inserts/updates", () => { beforeEach(async () => { + // This is isolation safe because this is the only file to use the CachedVideo table await CachedVideo.destroy({ where: {} }); }); afterEach(async () => { + // This is isolation safe because this is the only file to use the CachedVideo table await CachedVideo.destroy({ where: {} }); }); diff --git a/server/tests/unit/usermanager.spec.ts b/server/tests/unit/usermanager.spec.ts index d25397aa1..d2cc75b5d 100644 --- a/server/tests/unit/usermanager.spec.ts +++ b/server/tests/unit/usermanager.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; import usermanager from "../../usermanager"; import { conf } from "../../../server/ott-config"; import { FeatureDisabledException } from "../../exceptions"; diff --git a/server/vitest.config.ts b/server/vitest.config.ts new file mode 100644 index 000000000..c8bbfe29f --- /dev/null +++ b/server/vitest.config.ts @@ -0,0 +1,13 @@ +/// +import { defineConfig, configDefaults } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: [...configDefaults.exclude, "ts-out"], + pool: "forks", + setupFiles: ["./tests/unit/jest.setup.redis-mock.js"], + coverage: { + exclude: [...(configDefaults.coverage.exclude ?? []), "config/**", "migrations/**"], + }, + }, +}); diff --git a/yarn.lock b/yarn.lock index fa1eef6c8..00f03e10d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -76,7 +76,7 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.2": +"@babel/core@^7.11.6", "@babel/core@^7.12.3": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== @@ -118,7 +118,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.20.5", "@babel/generator@^7.23.6": +"@babel/generator@^7.20.5", "@babel/generator@^7.21.1", "@babel/generator@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== @@ -220,7 +220,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": +"@babel/helper-function-name@^7.21.0", "@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== @@ -228,7 +228,7 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" -"@babel/helper-hoist-variables@^7.22.5": +"@babel/helper-hoist-variables@^7.18.6", "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== @@ -436,7 +436,7 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== -"@babel/parser@^7.23.9": +"@babel/parser@^7.21.2", "@babel/parser@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== @@ -1108,7 +1108,7 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.20.5", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.23.7", "@babel/traverse@^7.7.2": +"@babel/traverse@^7.20.5", "@babel/traverse@^7.23.7": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== @@ -1124,6 +1124,22 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" + integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.21.1" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.2" + "@babel/types" "^7.21.2" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" @@ -2002,30 +2018,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.4.3.tgz#1f25a99f7f860e4c46423b5b1038262466fadde1" - integrity sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A== - dependencies: - "@jest/types" "^29.4.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.4.3" - jest-util "^29.4.3" - slash "^3.0.0" - -"@jest/console@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.5.0.tgz#593a6c5c0d3f75689835f1b3b4688c4f8544cb57" - integrity sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - slash "^3.0.0" - "@jest/console@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" @@ -2038,40 +2030,6 @@ jest-util "^29.7.0" slash "^3.0.0" -"@jest/core@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.5.0.tgz#76674b96904484e8214614d17261cc491e5f1f03" - integrity sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/reporters" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.5.0" - jest-config "^29.5.0" - jest-haste-map "^29.5.0" - jest-message-util "^29.5.0" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-resolve-dependencies "^29.5.0" - jest-runner "^29.5.0" - jest-runtime "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - jest-watcher "^29.5.0" - micromatch "^4.0.4" - pretty-format "^29.5.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - "@jest/core@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" @@ -2113,16 +2071,6 @@ dependencies: "@jest/types" "^29.6.3" -"@jest/environment@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.5.0.tgz#9152d56317c1fdb1af389c46640ba74ef0bb4c65" - integrity sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ== - dependencies: - "@jest/fake-timers" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-mock "^29.5.0" - "@jest/environment@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" @@ -2147,14 +2095,6 @@ dependencies: jest-get-type "^29.6.3" -"@jest/expect@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.5.0.tgz#80952f5316b23c483fbca4363ce822af79c38fba" - integrity sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g== - dependencies: - expect "^29.5.0" - jest-snapshot "^29.5.0" - "@jest/expect@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" @@ -2163,18 +2103,6 @@ expect "^29.7.0" jest-snapshot "^29.7.0" -"@jest/fake-timers@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.5.0.tgz#d4d09ec3286b3d90c60bdcd66ed28d35f1b4dc2c" - integrity sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg== - dependencies: - "@jest/types" "^29.5.0" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.5.0" - jest-mock "^29.5.0" - jest-util "^29.5.0" - "@jest/fake-timers@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" @@ -2187,16 +2115,6 @@ jest-mock "^29.7.0" jest-util "^29.7.0" -"@jest/globals@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.5.0.tgz#6166c0bfc374c58268677539d0c181f9c1833298" - integrity sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/expect" "^29.5.0" - "@jest/types" "^29.5.0" - jest-mock "^29.5.0" - "@jest/globals@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" @@ -2207,36 +2125,6 @@ "@jest/types" "^29.6.3" jest-mock "^29.7.0" -"@jest/reporters@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.5.0.tgz#985dfd91290cd78ddae4914ba7921bcbabe8ac9b" - integrity sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - jest-worker "^29.5.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - "@jest/reporters@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" @@ -2281,15 +2169,6 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/source-map@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.4.3.tgz#ff8d05cbfff875d4a791ab679b4333df47951d20" - integrity sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - "@jest/source-map@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" @@ -2299,26 +2178,6 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.4.3.tgz#e13d973d16c8c7cc0c597082d5f3b9e7f796ccb8" - integrity sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA== - dependencies: - "@jest/console" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-result@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.5.0.tgz#7c856a6ca84f45cc36926a4e9c6b57f1973f1408" - integrity sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - "@jest/test-result@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" @@ -2329,16 +2188,6 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz#34d7d82d3081abd523dbddc038a3ddcb9f6d3cc4" - integrity sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ== - dependencies: - "@jest/test-result" "^29.5.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - slash "^3.0.0" - "@jest/test-sequencer@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" @@ -2349,27 +2198,6 @@ jest-haste-map "^29.7.0" slash "^3.0.0" -"@jest/transform@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.5.0.tgz#cf9c872d0965f0cbd32f1458aa44a2b1988b00f9" - integrity sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.5.0" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-regex-util "^29.4.3" - jest-util "^29.5.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - "@jest/transform@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" @@ -2391,18 +2219,6 @@ slash "^3.0.0" write-file-atomic "^4.0.2" -"@jest/types@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.3.tgz#9069145f4ef09adf10cec1b2901b2d390031431f" - integrity sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA== - dependencies: - "@jest/schemas" "^29.4.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jest/types@^29.5.0": version "29.5.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" @@ -2502,7 +2318,7 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -3824,14 +3640,6 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/jest@29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.0.tgz#337b90bbcfe42158f39c2fb5619ad044bbb518ac" - integrity sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - "@types/js-cookie@^2.2.6": version "2.2.7" resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" @@ -3851,7 +3659,7 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -3962,11 +3770,6 @@ dependencies: "@types/express" "*" -"@types/prettier@^2.1.5": - version "2.7.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" - integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== - "@types/prop-types@*": version "15.7.11" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" @@ -4242,16 +4045,6 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@^2.5.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" - integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.34.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/parser@5.59.9": version "5.59.9" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.9.tgz#a85c47ccdd7e285697463da15200f9a8561dd5fa" @@ -4378,19 +4171,6 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== -"@typescript-eslint/typescript-estree@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" - integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - "@typescript-eslint/typescript-estree@5.59.9": version "5.59.9" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b" @@ -5224,13 +5004,6 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" -ansi-escapes@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.0.0.tgz#68c580e87a489f6df3d761028bb93093fde6bd8a" - integrity sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw== - dependencies: - type-fest "^3.0.0" - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -5529,19 +5302,6 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -babel-jest@29.5.0, babel-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.5.0.tgz#3fe3ddb109198e78b1c88f9ebdecd5e4fc2f50a5" - integrity sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q== - dependencies: - "@jest/transform" "^29.5.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.5.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -5574,16 +5334,6 @@ babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" - integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - babel-plugin-jest-hoist@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" @@ -5645,14 +5395,6 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" - integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== - dependencies: - babel-plugin-jest-hoist "^29.5.0" - babel-preset-current-node-syntax "^1.0.0" - babel-preset-jest@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" @@ -5837,13 +5579,6 @@ browserslist@^4.21.3: node-releases "^2.0.8" update-browserslist-db "^1.0.10" -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -6013,21 +5748,11 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" - integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -char-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" - integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== - check-error@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" @@ -7099,11 +6824,6 @@ decimal.js@^10.4.2: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== - dedent@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" @@ -7740,13 +7460,6 @@ eslint-plugin-deprecation@^2.0.0: tslib "^2.3.1" tsutils "^3.21.0" -eslint-plugin-jest@23.13.2: - version "23.13.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.13.2.tgz#7b7993b4e09be708c696b02555083ddefd7e4cc7" - integrity sha512-qZit+moTXTyZFNDqSIR88/L3rdBlTU7CuW6XmyErD2FfHEkdoLgThkRbiQjzgYnX6rfgLx3Ci4eJmF4Ui5v1Cw== - dependencies: - "@typescript-eslint/experimental-utils" "^2.5.0" - eslint-plugin-jsdoc@46.2.6: version "46.2.6" resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.2.6.tgz#f25590d371859f20691d65b5dcd4cbe370d65564" @@ -7852,7 +7565,7 @@ eslint-plugin-vue@9.7.0: vue-eslint-parser "^9.0.1" xml-name-validator "^4.0.0" -eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -7876,7 +7589,7 @@ eslint-scope@^7.2.0: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^2.0.0, eslint-utils@^2.1.0: +eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -8205,7 +7918,7 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.0.0, expect@^29.5.0: +expect@^29.0.0: version "29.5.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg== @@ -8353,7 +8066,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -8881,7 +8594,7 @@ glob@^10.2.7: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -9804,7 +9517,7 @@ istanbul-lib-coverage@^3.2.2: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: +istanbul-lib-instrument@^5.0.4: version "5.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== @@ -9889,14 +9602,6 @@ jackspeak@^2.3.5: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jest-changed-files@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" - integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -9906,32 +9611,6 @@ jest-changed-files@^29.7.0: jest-util "^29.7.0" p-limit "^3.1.0" -jest-circus@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.5.0.tgz#b5926989449e75bff0d59944bae083c9d7fb7317" - integrity sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/expect" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.5.0" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-runtime "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - p-limit "^3.1.0" - pretty-format "^29.5.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - jest-circus@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" @@ -9958,24 +9637,6 @@ jest-circus@^29.7.0: slash "^3.0.0" stack-utils "^2.0.3" -jest-cli@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.5.0.tgz#b34c20a6d35968f3ee47a7437ff8e53e086b4a67" - integrity sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw== - dependencies: - "@jest/core" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - prompts "^2.0.1" - yargs "^17.3.1" - jest-cli@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" @@ -9993,34 +9654,6 @@ jest-cli@^29.7.0: jest-validate "^29.7.0" yargs "^17.3.1" -jest-config@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.5.0.tgz#3cc972faec8c8aaea9ae158c694541b79f3748da" - integrity sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.5.0" - "@jest/types" "^29.5.0" - babel-jest "^29.5.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.5.0" - jest-environment-node "^29.5.0" - jest-get-type "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-runner "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.5.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - jest-config@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" @@ -10069,13 +9702,6 @@ jest-diff@^29.7.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-docblock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" - integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== - dependencies: - detect-newline "^3.0.0" - jest-docblock@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" @@ -10083,17 +9709,6 @@ jest-docblock@^29.7.0: dependencies: detect-newline "^3.0.0" -jest-each@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.5.0.tgz#fc6e7014f83eac68e22b7195598de8554c2e5c06" - integrity sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA== - dependencies: - "@jest/types" "^29.5.0" - chalk "^4.0.0" - jest-get-type "^29.4.3" - jest-util "^29.5.0" - pretty-format "^29.5.0" - jest-each@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" @@ -10119,18 +9734,6 @@ jest-environment-jsdom@^29.5.0: jest-util "^29.7.0" jsdom "^20.0.0" -jest-environment-node@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.5.0.tgz#f17219d0f0cc0e68e0727c58b792c040e332c967" - integrity sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/fake-timers" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-mock "^29.5.0" - jest-util "^29.5.0" - jest-environment-node@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" @@ -10153,25 +9756,6 @@ jest-get-type@^29.6.3: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== -jest-haste-map@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.5.0.tgz#69bd67dc9012d6e2723f20a945099e972b2e94de" - integrity sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA== - dependencies: - "@jest/types" "^29.5.0" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.4.3" - jest-util "^29.5.0" - jest-worker "^29.5.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - jest-haste-map@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" @@ -10191,14 +9775,6 @@ jest-haste-map@^29.7.0: optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz#cf4bdea9615c72bac4a3a7ba7e7930f9c0610c8c" - integrity sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow== - dependencies: - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - jest-leak-detector@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" @@ -10227,21 +9803,6 @@ jest-matcher-utils@^29.7.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-message-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.3.tgz#65b5280c0fdc9419503b49d4f48d4999d481cb5b" - integrity sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.4.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.4.3" - slash "^3.0.0" - stack-utils "^2.0.3" - jest-message-util@^29.5.0: version "29.5.0" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e" @@ -10272,15 +9833,6 @@ jest-message-util@^29.7.0: slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.5.0.tgz#26e2172bcc71d8b0195081ff1f146ac7e1518aed" - integrity sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-util "^29.5.0" - jest-mock@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" @@ -10295,24 +9847,11 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== -jest-regex-util@^29.0.0, jest-regex-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" - integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== - jest-regex-util@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== -jest-resolve-dependencies@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz#f0ea29955996f49788bf70996052aa98e7befee4" - integrity sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg== - dependencies: - jest-regex-util "^29.4.3" - jest-snapshot "^29.5.0" - jest-resolve-dependencies@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" @@ -10321,21 +9860,6 @@ jest-resolve-dependencies@^29.7.0: jest-regex-util "^29.6.3" jest-snapshot "^29.7.0" -jest-resolve@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.5.0.tgz#b053cc95ad1d5f6327f0ac8aae9f98795475ecdc" - integrity sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.5.0" - jest-validate "^29.5.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - jest-resolve@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" @@ -10351,33 +9875,6 @@ jest-resolve@^29.7.0: resolve.exports "^2.0.0" slash "^3.0.0" -jest-runner@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.5.0.tgz#6a57c282eb0ef749778d444c1d758c6a7693b6f8" - integrity sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/environment" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.4.3" - jest-environment-node "^29.5.0" - jest-haste-map "^29.5.0" - jest-leak-detector "^29.5.0" - jest-message-util "^29.5.0" - jest-resolve "^29.5.0" - jest-runtime "^29.5.0" - jest-util "^29.5.0" - jest-watcher "^29.5.0" - jest-worker "^29.5.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - jest-runner@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" @@ -10405,34 +9902,6 @@ jest-runner@^29.7.0: p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.5.0.tgz#c83f943ee0c1da7eb91fa181b0811ebd59b03420" - integrity sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/fake-timers" "^29.5.0" - "@jest/globals" "^29.5.0" - "@jest/source-map" "^29.4.3" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-message-util "^29.5.0" - jest-mock "^29.5.0" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - slash "^3.0.0" - strip-bom "^4.0.0" - jest-runtime@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" @@ -10461,35 +9930,6 @@ jest-runtime@^29.7.0: slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.5.0.tgz#c9c1ce0331e5b63cd444e2f95a55a73b84b1e8ce" - integrity sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.5.0" - graceful-fs "^4.2.9" - jest-diff "^29.5.0" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - natural-compare "^1.4.0" - pretty-format "^29.5.0" - semver "^7.3.5" - jest-snapshot@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" @@ -10516,18 +9956,6 @@ jest-snapshot@^29.7.0: pretty-format "^29.7.0" semver "^7.5.3" -jest-util@^29.0.0, jest-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.3.tgz#851a148e23fc2b633c55f6dad2e45d7f4579f496" - integrity sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q== - dependencies: - "@jest/types" "^29.4.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - jest-util@^29.5.0: version "29.5.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" @@ -10552,18 +9980,6 @@ jest-util@^29.7.0: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.5.0.tgz#8e5a8f36178d40e47138dc00866a5f3bd9916ffc" - integrity sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ== - dependencies: - "@jest/types" "^29.5.0" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.4.3" - leven "^3.1.0" - pretty-format "^29.5.0" - jest-validate@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" @@ -10576,47 +9992,6 @@ jest-validate@^29.7.0: leven "^3.1.0" pretty-format "^29.7.0" -jest-watch-typeahead@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-2.2.2.tgz#5516d3cd006485caa5cfc9bd1de40f1f8b136abf" - integrity sha512-+QgOFW4o5Xlgd6jGS5X37i08tuuXNW8X0CV9WNFi+3n8ExCIP+E1melYhvYLjv5fE6D0yyzk74vsSO8I6GqtvQ== - dependencies: - ansi-escapes "^6.0.0" - chalk "^5.2.0" - jest-regex-util "^29.0.0" - jest-watcher "^29.0.0" - slash "^5.0.0" - string-length "^5.0.1" - strip-ansi "^7.0.1" - -jest-watcher@^29.0.0: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.4.3.tgz#e503baa774f0c2f8f3c8db98a22ebf885f19c384" - integrity sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA== - dependencies: - "@jest/test-result" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.4.3" - string-length "^4.0.1" - -jest-watcher@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.5.0.tgz#cf7f0f949828ba65ddbbb45c743a382a4d911363" - integrity sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA== - dependencies: - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.5.0" - string-length "^4.0.1" - jest-watcher@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" @@ -10660,16 +10035,6 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.5.0.tgz#f75157622f5ce7ad53028f2f8888ab53e1f1f24e" - integrity sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ== - dependencies: - "@jest/core" "^29.5.0" - "@jest/types" "^29.5.0" - import-local "^3.0.2" - jest-cli "^29.5.0" - jest@^29.5.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" @@ -11068,7 +10433,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.memoize@4.x, lodash.memoize@^4.1.1: +lodash.memoize@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -11240,7 +10605,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x, make-error@^1.1.1: +make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -12681,15 +12046,6 @@ pretty-format@^29.0.0, pretty-format@^29.5.0: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-format@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.3.tgz#25500ada21a53c9e8423205cf0337056b201244c" - integrity sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA== - dependencies: - "@jest/schemas" "^29.4.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -14161,11 +13517,6 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -slash@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-5.0.0.tgz#8c18a871096b71ee0e002976a4fe3374991c3074" - integrity sha512-n6KkmvKS0623igEVj3FF0OZs1gYYJ0o0Hj939yc1fyxl2xt+xYpLnzJB6xBSqOfV9ZFLEWodBBN/heZJahuIJQ== - slate-base64-serializer@^0.2.112: version "0.2.115" resolved "https://registry.yarnpkg.com/slate-base64-serializer/-/slate-base64-serializer-0.2.115.tgz#438e051959bde013b50507f3144257e74039ff7f" @@ -14581,14 +13932,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-length@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e" - integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow== - dependencies: - char-regex "^2.0.0" - strip-ansi "^7.0.1" - string-template@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" @@ -15093,20 +14436,6 @@ ts-essentials@^9.3.0: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.3.2.tgz#5f4ae6d24e20d042a033316c0592dbb51d1b273f" integrity sha512-JxKJzuWqH1MmH4ZFHtJzGEhkfN3QvVR3C3w+4BIoWeoY68UVVoA2Np/Bca9z0IPSErVCWhv439aT0We4Dks8kQ== -ts-jest@29.1.1: - version "29.1.1" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" - integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" - ts-loader@8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f" @@ -15171,7 +14500,7 @@ tslib@^2.3.1, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tsutils@^3.17.1, tsutils@^3.21.0: +tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== @@ -15219,11 +14548,6 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-fest@^3.0.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.6.0.tgz#827c36c0e7fcff0cb2d55d091a5c4cf586432b8a" - integrity sha512-RqTRtKTzvPpNdDUp1dVkKQRunlPITk4mXeqFlAZoJsS+fLRn8AdPK0TcQDumGayhU7fjlBfiBjsq3pe3rIfXZQ== - type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -16195,7 +15519,7 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.7: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==