diff --git a/.c8rc.json b/.c8rc.json deleted file mode 100644 index 51d1ef9902c4..000000000000 --- a/.c8rc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "all": true, - "cache": false, - "extension": [".ts", ".js", ".jsx", ".tsx"], - "include": [ - "**/packages/**" - ], - "exclude": [ - "**/node_modules/**", - "**/test/**" - ], - "instrument": true, - "sourceMap": true, - "check-coverage": true, - "reporter": [ - "html", - "lcov", - "text", - "text-summary" - ] -} diff --git a/.eslintrc.js b/.eslintrc.js index 411eba578366..8eeda9a0446f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,6 +4,7 @@ module.exports = { browser: true, es6: true, node: true, + // Performance tests still use mocha mocha: true, }, globals: { @@ -110,7 +111,11 @@ module.exports = { "error", { groups: ["builtin", "external", "internal", "parent", "sibling", "index"], - pathGroups: [{pattern: "@lodestar/**", group: "internal"}], + pathGroups: [ + {pattern: "@lodestar/**", group: "internal"}, + // We want mocks to be imported before any internal code + {pattern: "**/mocks/**", group: "internal"}, + ], pathGroupsExcludedImportTypes: ["builtin"], }, ], @@ -201,24 +206,18 @@ module.exports = { }, { files: ["**/test/**/*.test.ts"], - plugins: ["mocha", "chai-expect"], - extends: ["plugin:mocha/recommended", "plugin:chai-expect/recommended"], + plugins: ["vitest"], + extends: ["plugin:vitest/recommended"], rules: { - // We observed that having multiple top level "describe" save valuable indentation - // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/max-top-level-suites.md - "mocha/max-top-level-suites": "off", - // We need to disable because we disabled "mocha/no-setup-in-describe" rule - // TODO: Move all setup code to before/beforeEach and then disable async describe - // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-async-describe.md - "mocha/no-async-describe": "off", - // Use of arrow functions are very common - "mocha/no-mocha-arrows": "off", - // It's common to call function inside describe block - // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-setup-in-describe.md - "mocha/no-setup-in-describe": "off", - // We use to split before in small isolated tasks - // https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-sibling-hooks.md - "mocha/no-sibling-hooks": "off", + "vitest/consistent-test-it": ["error", {fn: "it", withinDescribe: "it"}], + // We use a lot dynamic assertions so tests may not have usage of expect + "vitest/expect-expect": "off", + "vitest/no-disabled-tests": "warn", + "vitest/no-focused-tests": "error", + "vitest/prefer-called-with": "error", + "vitest/prefer-spy-on": "error", + // Our usage contains dynamic test title, this rule enforce static string value + "vitest/valid-title": "off", }, }, { diff --git a/.mocharc.yaml b/.mocharc.yaml deleted file mode 100644 index 1d24429fe466..000000000000 --- a/.mocharc.yaml +++ /dev/null @@ -1,4 +0,0 @@ -extension: ["ts"] -colors: true -node-option: - - "loader=ts-node/esm" diff --git a/.nycrc.json b/.nycrc.json deleted file mode 100644 index e0c09781c849..000000000000 --- a/.nycrc.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cache": false, - "extension": [".ts"], - "exclude": [ - "**/*.d.ts", - "**/*.js", - "**/lib/**", - "**/coverage/**", - "**/scripts/**", - "**/test/**", - "**/types/**", - "**/bin/**", - "**/node_modules/**" - ], - "all": false, - "reporter": ["lcovonly"] -} diff --git a/.wordlist.txt b/.wordlist.txt index 5982de7b50dc..9e9b2773bd66 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -84,6 +84,7 @@ UPnP UTF VM Vitalik +Vitest Wagyu api async @@ -174,6 +175,7 @@ scalability secp sepolia sharding +src ssz stakers subnet @@ -188,6 +190,7 @@ util utils validator validators +vitest wip xcode yaml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbc23571aa37..a4e67c4d226b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,15 +39,25 @@ Contributing to tests: - Do not pull unpinned versions from DockerHub (use deterministic tag) or Github (checkout commit not branch). - Carefully design tests that depend on timing sensitive events like p2p network e2e tests. Consider that Github runners are significantly less powerful than your development environment. +### Common Issues + +**Error: [vitest] Cannot mock "../../src/db/repositories/index.js" because it is already loaded by "src/db/beacon.ts"** + +If you observe any error in tests with matching to above error message, that implies you are loading the mocks in the wrong order. The correct order is to import the mocks first and then the actual module. We suggest to import the mocks on very top before any local modules. + +**✖ Error: Cannot find package 'async_hooks' imported from** + +If you observe following error running any of the test files that means you are running a file which itself or any dependency of that file imports `vitest`, but you are not running that file with `vitest` runner. Try running it with `yarn vitest` command, not with `node` command. + ### Debugging Spec Tests - To fix errors always focus on passing all minimal tests first without running mainnet tests. -- Spec tests often compare full expected vs actual states in JSON format. To better understand the diff it's convenient to use mocha's option `--inline-diffs`. -- A single logical error can cause many spec tests to fail. To focus on a single test at a time you can use mocha's option `--bail` to stop at the first failed test -- To then run only that failed test you can run against a specific file as use mocha's option `--grep` to run only one case +- Spec tests often compare full expected vs actual states in JSON format. +- A single logical error can cause many spec tests to fail. To focus on a single test at a time you can use vitest's option `--bail` to stop at the first failed test +- To then run only that failed test you can run against a specific file as use vitest's filters to run only one case ```sh -LODESTAR_PRESET=minimal ../../node_modules/.bin/mocha --config .mocharc.spec.yml test/spec/phase0/sanity.test.ts --inline-diffs --bail --grep "attestation" +LODESTAR_PRESET=minimal yarn vitest --run --config vitest.config.spec.ts test/spec/phase0/sanity.test.ts ``` ## Docker diff --git a/docs/pages/contribution/testing/integration-tests.md b/docs/pages/contribution/testing/integration-tests.md index b45110033460..dcf0201e4949 100644 --- a/docs/pages/contribution/testing/integration-tests.md +++ b/docs/pages/contribution/testing/integration-tests.md @@ -13,7 +13,7 @@ There are two ENV variables that are required to run this test: The command to run this test is: -`EL_BINARY_DIR=g11tech/geth:withdrawals EL_SCRIPT_DIR=gethdocker yarn mocha test/sim/withdrawal-interop.test.ts` +`EL_BINARY_DIR=g11tech/geth:withdrawals EL_SCRIPT_DIR=gethdocker yarn vitest --run test/sim/withdrawal-interop.test.ts` The images used by this test during CI are: diff --git a/karma.base.config.js b/karma.base.config.js deleted file mode 100644 index 0a4795593142..000000000000 --- a/karma.base.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - basePath: "", - frameworks: ["webpack", "mocha", "chai"], - files: ["test/unit/**/!(*.node).test.ts"], - exclude: [], - preprocessors: { - "test/**/*.ts": ["webpack"], - }, - reporters: ["spec"], - browsers: ["ChromeHeadless", "Electron", "FirefoxHeadless"], - singleRun: true, -}; diff --git a/package.json b/package.json index b422c2a604aa..93b364359a38 100644 --- a/package.json +++ b/package.json @@ -47,69 +47,45 @@ "devDependencies": { "@chainsafe/eslint-plugin-node": "^11.2.3", "@dapplion/benchmark": "^0.2.4", - "@types/chai": "^4.3.6", - "@types/chai-as-promised": "^7.1.6", - "@types/mocha": "^10.0.1", + "@types/mocha": "^10.0.6", "@types/node": "^20.6.5", - "@types/sinon": "^10.0.16", - "@types/sinon-chai": "^3.2.9", "@typescript-eslint/eslint-plugin": "6.7.2", "@typescript-eslint/parser": "6.7.2", - "@vitest/coverage-v8": "^1.1.0", - "@vitest/browser": "^1.1.0", - "c8": "^8.0.1", - "chai": "^4.3.8", - "chai-as-promised": "^7.1.1", + "@vitest/coverage-v8": "^1.2.1", + "@vitest/browser": "^1.2.1", "codecov": "^3.8.3", "crypto-browserify": "^3.12.0", "electron": "^26.2.2", "eslint": "^8.50.0", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-chai-expect": "^3.0.0", "eslint-plugin-import": "^2.28.1", - "eslint-plugin-mocha": "^10.2.0", "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-vitest": "^0.3.20", "https-browserify": "^1.0.0", "jsdom": "^23.0.1", - "karma": "^6.4.2", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^3.2.0", - "karma-cli": "^2.0.0", - "karma-electron": "^7.3.0", - "karma-firefox-launcher": "^2.1.2", - "karma-mocha": "^2.0.1", - "karma-spec-reporter": "^0.0.36", - "karma-webpack": "^5.0.0", "lerna": "^7.3.0", "libp2p": "1.1.1", "mocha": "^10.2.0", "node-gyp": "^9.4.0", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", "path-browserify": "^1.0.1", "prettier": "^3.0.3", "process": "^0.11.10", - "resolve-typescript-plugin": "^2.0.1", - "sinon": "^16.0.0", - "sinon-chai": "^3.7.0", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "supertest": "^6.3.3", - "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "typescript": "^5.2.2", "typescript-docs-verifier": "^2.5.0", - "vite-plugin-node-polyfills": "^0.18.0", + "vite-plugin-node-polyfills": "^0.19.0", "vite-plugin-top-level-await": "^1.4.1", - "vitest": "^1.1.0", - "vitest-when": "^0.3.0", + "vitest": "^1.2.1", + "vitest-when": "^0.3.1", "wait-port": "^1.1.0", - "webdriverio": "^8.27.0", - "webpack": "^5.88.2" + "webdriverio": "^8.28.0" }, "resolutions": { "dns-over-http-resolver": "^2.1.1", - "chai": "^4.3.10", "loupe": "^2.3.6", "vite": "^5.0.0" } diff --git a/packages/api/package.json b/packages/api/package.json index b7708ac5aa26..e1a52c47b489 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -65,7 +65,7 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit && yarn test:e2e", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "dependencies": { diff --git a/packages/api/test/utils/utils.ts b/packages/api/test/utils/utils.ts index 8faa2c90d187..cca89c8e4fd5 100644 --- a/packages/api/test/utils/utils.ts +++ b/packages/api/test/utils/utils.ts @@ -38,7 +38,6 @@ export function getTestServer(): {baseUrl: string; server: FastifyInstance} { return {baseUrl, server}; } -/** Type helper to get a Sinon mock object type with Api */ export function getMockApi>( routeIds: Record ): MockedObject> & ServerApi { diff --git a/packages/api/vitest.config.ts b/packages/api/vitest.config.ts index 9f325a6477e2..c4a84957259d 100644 --- a/packages/api/vitest.config.ts +++ b/packages/api/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 54c21fe032ab..3ddde8540670 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -77,15 +77,15 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit && yarn test:e2e", - "test:unit:minimal": "vitest --run --segfaultRetry 3 --dir test/unit/ --coverage", - "test:unit:mainnet": "LODESTAR_PRESET=mainnet nyc --cache-dir .nyc_output/.cache -e .ts mocha 'test/unit-mainnet/**/*.test.ts'", + "test:unit:minimal": "vitest --run --segfaultRetry 3 --dir test/unit/", + "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/unit-mainnet", "test:unit": "wrapper() { yarn test:unit:minimal $@ && yarn test:unit:mainnet $@; }; wrapper", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --poolOptions.threads.singleThread true --dir test/e2e", - "test:sim": "mocha 'test/sim/**/*.test.ts'", - "test:sim:merge-interop": "mocha 'test/sim/merge-interop.test.ts'", - "test:sim:mergemock": "mocha 'test/sim/mergemock.test.ts'", - "test:sim:withdrawals": "mocha 'test/sim/withdrawal-interop.test.ts'", - "test:sim:blobs": "mocha 'test/sim/4844-interop.test.ts'", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --config vitest.config.e2e.ts --dir test/e2e", + "test:sim": "vitest --run test/sim/**/*.test.ts", + "test:sim:merge-interop": "vitest --run test/sim/merge-interop.test.ts", + "test:sim:mergemock": "vitest --run test/sim/mergemock.test.ts", + "test:sim:withdrawals": "vitest --run test/sim/withdrawal-interop.test.ts", + "test:sim:blobs": "vitest --run test/sim/4844-interop.test.ts", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", "test:spec:bls": "vitest --run --config vitest.config.spec.ts --dir test/spec/bls/", "test:spec:general": "vitest --run --config vitest.config.spec.ts --dir test/spec/general/", diff --git a/packages/beacon-node/test/__mocks__/apiMocks.ts b/packages/beacon-node/test/__mocks__/apiMocks.ts deleted file mode 100644 index 0f0316ed7435..000000000000 --- a/packages/beacon-node/test/__mocks__/apiMocks.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import {config} from "@lodestar/config/default"; -import {ChainForkConfig} from "@lodestar/config"; -import {getBeaconBlockApi} from "../../src/api/impl/beacon/blocks/index.js"; -import {getMockedBeaconChain, MockedBeaconChain} from "./mockedBeaconChain.js"; -import {MockedBeaconSync, getMockedBeaconSync} from "./beaconSyncMock.js"; -import {MockedBeaconDb, getMockedBeaconDb} from "./mockedBeaconDb.js"; -import {MockedNetwork, getMockedNetwork} from "./mockedNetwork.js"; - -export type ApiImplTestModules = { - forkChoiceStub: MockedBeaconChain["forkChoice"]; - chainStub: MockedBeaconChain; - syncStub: MockedBeaconSync; - dbStub: MockedBeaconDb; - networkStub: MockedNetwork; - blockApi: ReturnType; - config: ChainForkConfig; -}; - -export function setupApiImplTestServer(): ApiImplTestModules { - const chainStub = getMockedBeaconChain(); - const forkChoiceStub = chainStub.forkChoice; - const syncStub = getMockedBeaconSync(); - const dbStub = getMockedBeaconDb(); - const networkStub = getMockedNetwork(); - - const blockApi = getBeaconBlockApi({ - chain: chainStub, - config, - db: dbStub, - network: networkStub, - metrics: null, - }); - - return { - forkChoiceStub, - chainStub, - syncStub, - dbStub, - networkStub, - blockApi, - config, - }; -} diff --git a/packages/beacon-node/test/__mocks__/mockedBeaconDb.ts b/packages/beacon-node/test/__mocks__/mockedBeaconDb.ts deleted file mode 100644 index cb760cd055b8..000000000000 --- a/packages/beacon-node/test/__mocks__/mockedBeaconDb.ts +++ /dev/null @@ -1,66 +0,0 @@ -import {vi, MockedObject} from "vitest"; -import {LevelDbController} from "@lodestar/db"; -import {config as minimalConfig} from "@lodestar/config/default"; -import {BeaconDb} from "../../src/db/index.js"; -import { - AttesterSlashingRepository, - BlockArchiveRepository, - BlockRepository, - DepositEventRepository, - DepositDataRootRepository, - Eth1DataRepository, - ProposerSlashingRepository, - StateArchiveRepository, - VoluntaryExitRepository, - BLSToExecutionChangeRepository, - BlobSidecarsRepository, - BlobSidecarsArchiveRepository, -} from "../../src/db/repositories/index.js"; - -vi.mock("@lodestar/db"); -vi.mock("../../src/db/repositories/index.js"); - -export class MockedBeaconDb extends BeaconDb { - db!: MockedObject; - - block: MockedObject; - blockArchive: MockedObject; - - blobSidecars: MockedObject; - blobSidecarsArchive: MockedObject; - - stateArchive: MockedObject; - - voluntaryExit: MockedObject; - blsToExecutionChange: MockedObject; - proposerSlashing: MockedObject; - attesterSlashing: MockedObject; - depositEvent: MockedObject; - - depositDataRoot: MockedObject; - eth1Data: MockedObject; - - constructor(config = minimalConfig) { - // eslint-disable-next-line - super(config, {} as any); - this.block = vi.mocked(new BlockRepository({} as any, {} as any)); - this.blockArchive = vi.mocked(new BlockArchiveRepository({} as any, {} as any)); - this.stateArchive = vi.mocked(new StateArchiveRepository({} as any, {} as any)); - - this.voluntaryExit = vi.mocked(new VoluntaryExitRepository({} as any, {} as any)); - this.blsToExecutionChange = vi.mocked(new BLSToExecutionChangeRepository({} as any, {} as any)); - this.proposerSlashing = vi.mocked(new ProposerSlashingRepository({} as any, {} as any)); - this.attesterSlashing = vi.mocked(new AttesterSlashingRepository({} as any, {} as any)); - this.depositEvent = vi.mocked(new DepositEventRepository({} as any, {} as any)); - - this.depositDataRoot = vi.mocked(new DepositDataRootRepository({} as any, {} as any)); - this.eth1Data = vi.mocked(new Eth1DataRepository({} as any, {} as any)); - - this.blobSidecars = vi.mocked(new BlobSidecarsRepository({} as any, {} as any)); - this.blobSidecarsArchive = vi.mocked(new BlobSidecarsArchiveRepository({} as any, {} as any)); - } -} - -export function getMockedBeaconDb(): MockedBeaconDb { - return new MockedBeaconDb(); -} diff --git a/packages/beacon-node/test/__mocks__/mockedNetwork.ts b/packages/beacon-node/test/__mocks__/mockedNetwork.ts deleted file mode 100644 index 969dff5e6355..000000000000 --- a/packages/beacon-node/test/__mocks__/mockedNetwork.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {vi, MockedObject} from "vitest"; -import {Network} from "../../src/network/index.js"; - -export type MockedNetwork = MockedObject; - -vi.mock("../../src/network/index.js"); - -export function getMockedNetwork(): MockedNetwork { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - return vi.mocked(new Network()) as MockedNetwork; -} diff --git a/packages/beacon-node/test/e2e/api/impl/beacon/state/endpoint.test.ts b/packages/beacon-node/test/e2e/api/impl/beacon/state/endpoint.test.ts index 81932a3d446d..182d7b3430b4 100644 --- a/packages/beacon-node/test/e2e/api/impl/beacon/state/endpoint.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/beacon/state/endpoint.test.ts @@ -43,7 +43,7 @@ describe("beacon state api", function () { await bn.close(); }); - describe("getEpochCommittees", async () => { + describe("getEpochCommittees", () => { it("should return all committees for the given state", async () => { const res = await client.getEpochCommittees("head"); ApiError.assert(res); diff --git a/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts b/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts index 4bc98cfa16dc..8a1d1585ec2d 100644 --- a/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts +++ b/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts @@ -91,9 +91,11 @@ describe.skip("doppelganger / doppelganger test", function () { const beaconBlock = ssz.allForks.phase0.BeaconBlock.defaultValue(); await expect( - validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot), + validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot) + ).resolves.toBeWithMessage( + undefined, "Signing should be possible if starting at genesis since doppelganger should be off" - ).to.eventually.be.fulfilled; + ); await expect( validatorUnderTest.validatorStore.signAttestation( @@ -105,9 +107,11 @@ describe.skip("doppelganger / doppelganger test", function () { bn.chain.clock.currentSlot ), bn.chain.clock.currentEpoch - ), + ) + ).resolves.toBeWithMessage( + undefined, "Signing should be possible if starting at genesis since doppelganger should be off" - ).to.eventually.be.fulfilled; + ); }); it("should shut down validator if same key is active and started after genesis", async function () { @@ -241,18 +245,18 @@ describe.skip("doppelganger / doppelganger test", function () { await expect( validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot) - ).to.eventually.be.rejectedWith(`Doppelganger state for key ${pubKey} is not safe`); + ).rejects.toThrow(`Doppelganger state for key ${pubKey} is not safe`); await expect( validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot) - ).to.eventually.be.rejectedWith(`Doppelganger state for key ${pubKey} is not safe`); + ).rejects.toThrow(`Doppelganger state for key ${pubKey} is not safe`); await waitForEvent(bn.chain.clock, ClockEvent.epoch, timeout); + // Signing should be possible after doppelganger check has elapsed await expect( - validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot), - "Signing should be possible after doppelganger check has elapsed" - ).to.eventually.be.fulfilled; + validatorUnderTest.validatorStore.signBlock(fromHexString(pubKey), beaconBlock, bn.chain.clock.currentSlot) + ).resolves.toBeUndefined(); }); it("should not sign attestations if doppelganger period has not passed and started after genesis", async function () { @@ -282,7 +286,7 @@ describe.skip("doppelganger / doppelganger test", function () { ), bn.chain.clock.currentEpoch ) - ).to.eventually.be.rejectedWith(`Doppelganger state for key ${pubKey} is not safe`); + ).rejects.toThrow(`Doppelganger state for key ${pubKey} is not safe`); await expect( validatorUnderTest.validatorStore.signAttestation( @@ -290,10 +294,11 @@ describe.skip("doppelganger / doppelganger test", function () { generateAttestationData(bn.chain.clock.currentSlot, bn.chain.clock.currentEpoch), bn.chain.clock.currentEpoch ) - ).to.eventually.be.rejectedWith(`Doppelganger state for key ${pubKey} is not safe`); + ).rejects.toThrow(`Doppelganger state for key ${pubKey} is not safe`); await waitForEvent(bn.chain.clock, ClockEvent.epoch, timeout); + // Signing should be possible after doppelganger check has elapsed await expect( validatorUnderTest.validatorStore.signAttestation( createAttesterDuty(fromHexString(pubKey), bn.chain.clock.currentSlot, committeeIndex, validatorIndex), @@ -304,9 +309,8 @@ describe.skip("doppelganger / doppelganger test", function () { bn.chain.clock.currentSlot ), bn.chain.clock.currentEpoch - ), - "Signing should be possible after doppelganger check has elapsed" - ).to.eventually.be.fulfilled; + ) + ).resolves.toBeUndefined(); }); }); diff --git a/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts b/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts index 85eecb7c742e..ae3e0c707542 100644 --- a/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts +++ b/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts @@ -110,8 +110,6 @@ describe.skip("eth1 / Eth1MergeBlockTracker", function () { // Given the total difficulty offset the block that has TTD is the `difficultyOffset`nth block const mergeBlock = await eth1MergeBlockTracker.getTerminalPowBlock(); if (!mergeBlock) throw Error("mergeBlock not found"); - // Chai does not support bigint comparison - // eslint-disable-next-line chai-expect/no-inner-compare // "mergeBlock.totalDifficulty is not >= TTD" expect(mergeBlock.totalDifficulty).toBeGreaterThanOrEqual(terminalTotalDifficulty); }); @@ -146,8 +144,6 @@ describe.skip("eth1 / Eth1MergeBlockTracker", function () { // Given the total difficulty offset the block that has TTD is the `difficultyOffset`nth block const mergeBlock = await eth1MergeBlockTracker.getTerminalPowBlock(); if (!mergeBlock) throw Error("mergeBlock not found"); - // Chai does not support bigint comparison - // eslint-disable-next-line chai-expect/no-inner-compare // "mergeBlock.totalDifficulty is not >= TTD" expect(mergeBlock.totalDifficulty).toBeGreaterThanOrEqual(terminalTotalDifficulty); }); diff --git a/packages/beacon-node/test/e2e/network/gossipsub.test.ts b/packages/beacon-node/test/e2e/network/gossipsub.test.ts index 1c7a57650eca..0ffab720598c 100644 --- a/packages/beacon-node/test/e2e/network/gossipsub.test.ts +++ b/packages/beacon-node/test/e2e/network/gossipsub.test.ts @@ -5,7 +5,8 @@ import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; import {Network} from "../../../src/network/index.js"; import {GossipType, GossipHandlers, GossipHandlerParamGeneric} from "../../../src/network/gossip/index.js"; -import {connect, onPeerConnect, getNetworkForTest} from "../../utils/network.js"; +import {getNetworkForTest} from "../../utils/networkWithMockDb.js"; +import {connect, onPeerConnect} from "../../utils/network.js"; describe( "gossipsub / main thread", @@ -23,8 +24,6 @@ describe( {timeout: 10_000} ); -/* eslint-disable mocha/no-top-level-hooks */ - function runTests({useWorker}: {useWorker: boolean}): void { const afterEachCallbacks: (() => Promise | void)[] = []; afterEach(async () => { diff --git a/packages/beacon-node/test/e2e/network/mdns.test.ts b/packages/beacon-node/test/e2e/network/mdns.test.ts index 91cbab09bae9..d8e148e191fe 100644 --- a/packages/beacon-node/test/e2e/network/mdns.test.ts +++ b/packages/beacon-node/test/e2e/network/mdns.test.ts @@ -6,24 +6,21 @@ import {SignableENR} from "@chainsafe/enr"; import {createBeaconConfig} from "@lodestar/config"; import {config} from "@lodestar/config/default"; import {ssz} from "@lodestar/types"; - import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; +import {getMockedBeaconChain} from "../../mocks/mockedBeaconChain.js"; +import {getMockedBeaconDb} from "../../mocks/mockedBeaconDb.js"; import {Network, NetworkInitModules, getReqRespHandlers} from "../../../src/network/index.js"; import {defaultNetworkOptions, NetworkOptions} from "../../../src/network/options.js"; -import {zeroProtoBlock} from "../../utils/mocks/chain.js"; import {createNetworkModules, onPeerConnect} from "../../utils/network.js"; -import {generateState} from "../../utils/state.js"; +import {generateState, zeroProtoBlock} from "../../utils/state.js"; import {testLogger} from "../../utils/logger.js"; import {GossipHandlers} from "../../../src/network/gossip/index.js"; import {memoOnce} from "../../utils/cache.js"; -import {getMockedBeaconChain} from "../../__mocks__/mockedBeaconChain.js"; -import {getMockedBeaconDb} from "../../__mocks__/mockedBeaconDb.js"; let port = 9000; const mu = "/ip4/127.0.0.1/tcp/0"; // https://github.com/ChainSafe/lodestar/issues/5967 -// eslint-disable-next-line mocha/no-skipped-tests describe.skip("mdns", function () { const afterEachCallbacks: (() => Promise | void)[] = []; afterEach(async () => { diff --git a/packages/beacon-node/test/e2e/network/network.test.ts b/packages/beacon-node/test/e2e/network/network.test.ts index 2a727481118b..40bf6b7e14af 100644 --- a/packages/beacon-node/test/e2e/network/network.test.ts +++ b/packages/beacon-node/test/e2e/network/network.test.ts @@ -5,7 +5,8 @@ import {phase0} from "@lodestar/types"; import {sleep} from "@lodestar/utils"; import {Network, NetworkEvent, ReqRespMethod} from "../../../src/network/index.js"; import {GoodByeReasonCode} from "../../../src/constants/index.js"; -import {connect, disconnect, onPeerConnect, onPeerDisconnect, getNetworkForTest} from "../../utils/network.js"; +import {connect, disconnect, onPeerConnect, onPeerDisconnect} from "../../utils/network.js"; +import {getNetworkForTest} from "../../utils/networkWithMockDb.js"; import {getValidPeerId} from "../../utils/peer.js"; describe( @@ -24,8 +25,6 @@ describe( {timeout: 10_000} ); -/* eslint-disable mocha/no-top-level-hooks */ - function runTests({useWorker}: {useWorker: boolean}): void { const afterEachCallbacks: (() => Promise | void)[] = []; @@ -98,7 +97,7 @@ function runTests({useWorker}: {useWorker: boolean}): void { // Current implementation of discv5 consumer doesn't allow to deterministically force a peer to be found // a random find node lookup can yield no results if there are too few peers in the DHT - // it.skip("should connect to new peer by subnet", async function () {}); + it.todo("should connect to new peer by subnet", async function () {}); it("Should goodbye peers on stop", async function () { const [netA, netB] = await createTestNodesAB(); diff --git a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts index 5ef836761cb6..8eb0ecdd1ba4 100644 --- a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts +++ b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts @@ -1,7 +1,6 @@ -import {describe, it, afterEach, expect} from "vitest"; +import {describe, it, afterEach, expect, vi} from "vitest"; import {Connection} from "@libp2p/interface"; import {CustomEvent} from "@libp2p/interface"; -import sinon from "sinon"; import {BitArray} from "@chainsafe/ssz"; import {config} from "@lodestar/config/default"; import {altair, phase0, ssz} from "@lodestar/types"; @@ -11,7 +10,8 @@ import {ReqRespMethod} from "../../../../src/network/reqresp/ReqRespBeaconNode.j import {PeerRpcScoreStore, PeerManager, IReqRespBeaconNodePeerManager} from "../../../../src/network/peers/index.js"; import {Eth2Gossipsub, getConnectionsMap, NetworkEvent, NetworkEventBus} from "../../../../src/network/index.js"; import {PeersData} from "../../../../src/network/peers/peersData.js"; -import {createNode, getAttnets, getSyncnets} from "../../../utils/network.js"; +import {createNode} from "../../../utils/network.js"; +import {getAttnets, getSyncnets} from "../../../utils/network.js"; import {generateState} from "../../../utils/state.js"; import {waitForEvent} from "../../../utils/events/resolver.js"; import {testLogger} from "../../../utils/logger.js"; @@ -102,10 +102,10 @@ describe("network / peers / PeerManager", function () { // Create a real event emitter with stubbed methods class ReqRespFake implements IReqRespBeaconNodePeerManager { - sendStatus = sinon.stub(); - sendMetadata = sinon.stub(); - sendGoodbye = sinon.stub(); - sendPing = sinon.stub(); + sendStatus = vi.fn(); + sendMetadata = vi.fn(); + sendGoodbye = vi.fn(); + sendPing = vi.fn(); } it("Should request metadata on receivedPing of unknown peer", async () => { @@ -126,7 +126,7 @@ describe("network / peers / PeerManager", function () { const metadata: phase0.Metadata = {seqNumber, attnets: BitArray.fromBitLen(0)}; // Simulate peer1 responding with its metadata - reqResp.sendMetadata.resolves(metadata); + reqResp.sendMetadata.mockResolvedValue(metadata); // We get a ping by peer1, don't have it's metadata so it gets requested networkEventBus.emit(NetworkEvent.reqRespRequest, { @@ -134,20 +134,20 @@ describe("network / peers / PeerManager", function () { peer: peerId1, }); - expect(reqResp.sendMetadata.callCount).toBe(1); - expect(reqResp.sendMetadata.getCall(0).args[0]).toBe(peerId1); + expect(reqResp.sendMetadata).toHaveBeenCalledOnce(); + expect(reqResp.sendMetadata).toHaveBeenNthCalledWith(1, peerId1); // Allow requestMetadata promise to resolve await sleep(0); // We get another ping by peer1, but with an already known seqNumber - reqResp.sendMetadata.reset(); + reqResp.sendMetadata.mockReset(); networkEventBus.emit(NetworkEvent.reqRespRequest, { request: {method: ReqRespMethod.Ping, body: seqNumber}, peer: peerId1, }); - expect(reqResp.sendMetadata.callCount).toBe(0); + expect(reqResp.sendMetadata).not.toHaveBeenCalledOnce(); }); const libp2pConnectionOutboud = { @@ -187,9 +187,9 @@ describe("network / peers / PeerManager", function () { // Simulate peer1 returning a PING and STATUS message const remoteStatus = statusCache.get(); const remoteMetadata: altair.Metadata = {seqNumber: BigInt(1), attnets: getAttnets(), syncnets: getSyncnets()}; - reqResp.sendPing.resolves(remoteMetadata.seqNumber); - reqResp.sendStatus.resolves(remoteStatus); - reqResp.sendMetadata.resolves(remoteMetadata); + reqResp.sendPing.mockResolvedValue(remoteMetadata.seqNumber); + reqResp.sendStatus.mockResolvedValue(remoteStatus); + reqResp.sendMetadata.mockResolvedValue(remoteMetadata); // Simualate a peer connection, get() should return truthy getConnectionsMap(libp2p).set(peerId1.toString(), [libp2pConnectionOutboud]); @@ -207,9 +207,9 @@ describe("network / peers / PeerManager", function () { // 2. Call reqResp.sendStatus // 3. Receive ping result (1) and call reqResp.sendMetadata // 4. Receive status result (2) assert peer relevance and emit `PeerManagerEvent.peerConnected` - expect(reqResp.sendPing.callCount).toBe(1); - expect(reqResp.sendStatus.callCount).toBe(1); - expect(reqResp.sendMetadata.callCount).toBe(1); + expect(reqResp.sendPing).toHaveBeenCalledOnce(); + expect(reqResp.sendStatus).toHaveBeenCalledOnce(); + expect(reqResp.sendMetadata).toHaveBeenCalledOnce(); expect(peerManager["connectedPeers"].get(peerId1.toString())?.metadata).toEqual(remoteMetadata); }); diff --git a/packages/beacon-node/test/e2e/network/reqresp.test.ts b/packages/beacon-node/test/e2e/network/reqresp.test.ts index ee573973131d..855dc7046203 100644 --- a/packages/beacon-node/test/e2e/network/reqresp.test.ts +++ b/packages/beacon-node/test/e2e/network/reqresp.test.ts @@ -7,13 +7,13 @@ import {allForks, altair, phase0, Root, ssz} from "@lodestar/types"; import {sleep as _sleep} from "@lodestar/utils"; import {Network, ReqRespBeaconNodeOpts} from "../../../src/network/index.js"; import {expectRejectedWithLodestarError} from "../../utils/errors.js"; -import {connect, getNetworkForTest, getPeerIdOf, onPeerConnect} from "../../utils/network.js"; +import {connect, getPeerIdOf, onPeerConnect} from "../../utils/network.js"; +import {getNetworkForTest} from "../../utils/networkWithMockDb.js"; import {arrToSource} from "../../unit/network/reqresp/utils.js"; import {GetReqRespHandlerFn, ReqRespMethod} from "../../../src/network/reqresp/types.js"; import {PeerIdStr} from "../../../src/util/peerId.js"; /* eslint-disable - mocha/no-top-level-hooks, require-yield, @typescript-eslint/naming-convention, @typescript-eslint/explicit-function-return-type @@ -84,53 +84,6 @@ function runTests({useWorker}: {useWorker: boolean}): void { return [netA, netB, await getPeerIdOf(netA), await getPeerIdOf(netB)]; } - // it("should send/receive a ping message", async function () { - // const [netA, netB] = await createAndConnectPeers(); - - // // Modify the metadata to make the seqNumber non-zero - // netB.metadata.attnets = BitArray.fromBitLen(0); - // netB.metadata.attnets = BitArray.fromBitLen(0); - // const expectedPong = netB.metadata.seqNumber; - // expect(expectedPong.toString()).to.deep.equal("2", "seqNumber"); - - // const pong = await netA.reqResp.ping(peerIdB); - // expect(pong.toString()).to.deep.equal(expectedPong.toString(), "Wrong response body"); - // }); - - // it("should send/receive a metadata message - altair", async function () { - // const [netA, netB] = await createAndConnectPeers(); - - // const metadata: altair.Metadata = { - // seqNumber: netB.metadata.seqNumber, - // attnets: netB.metadata.attnets, - // syncnets: netB.metadata.syncnets, - // }; - - // const receivedMetadata = await netA.reqResp.metadata(peerIdB); - // expect(receivedMetadata).to.deep.equal(metadata, "Wrong response body"); - // }); - - // it("should send/receive a status message", async function () { - // const status: phase0.Status = { - // forkDigest: Buffer.alloc(4, 0), - // finalizedRoot: Buffer.alloc(32, 0), - // finalizedEpoch: 0, - // headRoot: Buffer.alloc(32, 0), - // headSlot: 0, - // }; - // const statusNetA: phase0.Status = {...status, finalizedEpoch: 1}; - // const statusNetB: phase0.Status = {...status, finalizedEpoch: 2}; - - // const [netA, netB] = await createAndConnectPeers({ - // onStatus: async function* onRequest() { - // yield {data: ssz.phase0.Status.serialize(statusNetB), fork: ForkName.phase0}; - // }, - // }); - - // const receivedStatus = await netA.reqResp.status(peerIdB, statusNetA); - // expect(receivedStatus).to.deep.equal(statusNetB, "Wrong response body"); - // }); - it("should send/receive signed blocks", async function () { const req: phase0.BeaconBlocksByRangeRequest = {startSlot: 0, step: 1, count: 2}; const blocks: phase0.SignedBeaconBlock[] = []; diff --git a/packages/beacon-node/test/__mocks__/beaconSyncMock.ts b/packages/beacon-node/test/mocks/beaconSyncMock.ts similarity index 51% rename from packages/beacon-node/test/__mocks__/beaconSyncMock.ts rename to packages/beacon-node/test/mocks/beaconSyncMock.ts index 6f0e2bd36d62..00164afc5d63 100644 --- a/packages/beacon-node/test/__mocks__/beaconSyncMock.ts +++ b/packages/beacon-node/test/mocks/beaconSyncMock.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {MockedObject, vi} from "vitest"; +import {Mocked, vi} from "vitest"; import {BeaconSync} from "../../src/sync/index.js"; -export type MockedBeaconSync = MockedObject; +export type MockedBeaconSync = Mocked; -vi.mock("../../src/sync/index.js", async (requireActual) => { - const mod = await requireActual(); +vi.mock("../../src/sync/index.js", async (importActual) => { + const mod = await importActual(); const BeaconSync = vi.fn().mockImplementation(() => { const sync = {}; @@ -21,7 +21,7 @@ vi.mock("../../src/sync/index.js", async (requireActual) => { }); export function getMockedBeaconSync(): MockedBeaconSync { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - return vi.mocked(new BeaconSync({})) as MockedBeaconSync; + return vi.mocked(new BeaconSync({} as any, {} as any)); } + +vi.resetModules(); diff --git a/packages/beacon-node/test/utils/mocks/clock.ts b/packages/beacon-node/test/mocks/clock.ts similarity index 96% rename from packages/beacon-node/test/utils/mocks/clock.ts rename to packages/beacon-node/test/mocks/clock.ts index e4aeb21c1e90..155334909560 100644 --- a/packages/beacon-node/test/utils/mocks/clock.ts +++ b/packages/beacon-node/test/mocks/clock.ts @@ -1,7 +1,7 @@ import EventEmitter from "node:events"; import {computeEpochAtSlot} from "@lodestar/state-transition"; import {Epoch, Slot} from "@lodestar/types"; -import {IClock} from "../../../src/util/clock.js"; +import {IClock} from "../../src/util/clock.js"; /** * Mock clock that does not progress time unless calling setSlot() diff --git a/packages/beacon-node/test/__mocks__/loggerMock.ts b/packages/beacon-node/test/mocks/loggerMock.ts similarity index 70% rename from packages/beacon-node/test/__mocks__/loggerMock.ts rename to packages/beacon-node/test/mocks/loggerMock.ts index bafd81230dea..ee25ede93475 100644 --- a/packages/beacon-node/test/__mocks__/loggerMock.ts +++ b/packages/beacon-node/test/mocks/loggerMock.ts @@ -1,7 +1,7 @@ -import {vi, MockedObject} from "vitest"; +import {vi, Mocked} from "vitest"; import {Logger} from "@lodestar/logger"; -export type MockedLogger = MockedObject; +export type MockedLogger = Mocked; export function getMockedLogger(): MockedLogger { return { diff --git a/packages/beacon-node/test/__mocks__/mockedBeaconChain.ts b/packages/beacon-node/test/mocks/mockedBeaconChain.ts similarity index 51% rename from packages/beacon-node/test/__mocks__/mockedBeaconChain.ts rename to packages/beacon-node/test/mocks/mockedBeaconChain.ts index c72d22471ce8..21881875ba61 100644 --- a/packages/beacon-node/test/__mocks__/mockedBeaconChain.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconChain.ts @@ -1,54 +1,110 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {vi, MockedObject, Mock} from "vitest"; -import {ForkChoice} from "@lodestar/fork-choice"; +import {vi, Mocked, Mock} from "vitest"; import {config as defaultConfig} from "@lodestar/config/default"; import {ChainForkConfig} from "@lodestar/config"; -import {BeaconChain} from "../../src/chain/index.js"; -import {ExecutionEngineHttp} from "../../src/execution/engine/http.js"; +import {ForkChoice, ProtoBlock, EpochDifference} from "@lodestar/fork-choice"; +import {Logger} from "@lodestar/utils"; +import {BeaconChain} from "../../src/chain/chain.js"; +import {ChainEventEmitter} from "../../src/chain/emitter.js"; +import {ExecutionEngineHttp} from "../../src/execution/engine/index.js"; import {ExecutionBuilderHttp} from "../../src/execution/builder/http.js"; import {Eth1ForBlockProduction} from "../../src/eth1/index.js"; -import {OpPool} from "../../src/chain/opPools/opPool.js"; -import {AggregatedAttestationPool} from "../../src/chain/opPools/aggregatedAttestationPool.js"; +import {OpPool, AggregatedAttestationPool} from "../../src/chain/opPools/index.js"; import {BeaconProposerCache} from "../../src/chain/beaconProposerCache.js"; -import {QueuedStateRegenerator} from "../../src/chain/regen/index.js"; import {LightClientServer} from "../../src/chain/lightClient/index.js"; import {Clock} from "../../src/util/clock.js"; +import {QueuedStateRegenerator} from "../../src/chain/regen/index.js"; import {ShufflingCache} from "../../src/chain/shufflingCache.js"; import {getMockedLogger} from "./loggerMock.js"; -export type MockedBeaconChain = MockedObject & { +export type MockedBeaconChain = Mocked & { + logger: Mocked; getHeadState: Mock<[]>; - forkChoice: MockedObject; - executionEngine: MockedObject; - executionBuilder: MockedObject; - eth1: MockedObject; - opPool: MockedObject; - aggregatedAttestationPool: MockedObject; - beaconProposerCache: MockedObject; - shufflingCache: MockedObject; - regen: MockedObject; + forkChoice: MockedForkChoice; + executionEngine: Mocked; + executionBuilder: Mocked; + eth1: Mocked; + opPool: Mocked; + aggregatedAttestationPool: Mocked; + beaconProposerCache: Mocked; + shufflingCache: Mocked; + regen: Mocked; bls: { verifySignatureSets: Mock<[boolean]>; verifySignatureSetsSameMessage: Mock<[boolean]>; close: Mock; canAcceptWork: Mock<[boolean]>; }; - lightClientServer: MockedObject; + lightClientServer: Mocked; }; -vi.mock("@lodestar/fork-choice"); -vi.mock("../../src/execution/engine/http.js"); -vi.mock("../../src/execution/builder/http.js"); + +vi.mock("@lodestar/fork-choice", async (importActual) => { + const mod = await importActual(); + + const ForkChoice = vi.fn().mockImplementation(() => { + return { + updateTime: vi.fn(), + getJustifiedBlock: vi.fn(), + getFinalizedBlock: vi.fn(), + getHead: vi.fn(), + getHeadRoot: vi.fn(), + getDependentRoot: vi.fn(), + getBlockHex: vi.fn(), + getAllAncestorBlocks: vi.fn(), + getAllNonAncestorBlocks: vi.fn(), + iterateAncestorBlocks: vi.fn(), + getBlockSummariesByParentRoot: vi.fn(), + getCanonicalBlockAtSlot: vi.fn(), + getFinalizedCheckpoint: vi.fn(), + hasBlockHex: vi.fn(), + getBlockSummariesAtSlot: vi.fn(), + }; + }); + + return { + ...mod, + ForkChoice, + }; +}); + +vi.mock("../../src/chain/regen/index.js"); vi.mock("../../src/eth1/index.js"); -vi.mock("../../src/chain/opPools/opPool.js"); -vi.mock("../../src/chain/opPools/aggregatedAttestationPool.js"); vi.mock("../../src/chain/beaconProposerCache.js"); vi.mock("../../src/chain/shufflingCache.js"); -vi.mock("../../src/chain/regen/index.js"); vi.mock("../../src/chain/lightClient/index.js"); -vi.mock("../../src/chain/index.js", async (requireActual) => { - const mod = await requireActual(); + +vi.mock("../../src/chain/opPools/index.js", async (importActual) => { + const mod = await importActual(); + + const OpPool = vi.fn().mockImplementation(() => { + return { + hasSeenBlsToExecutionChange: vi.fn(), + hasSeenVoluntaryExit: vi.fn(), + hasSeenProposerSlashing: vi.fn(), + hasSeenAttesterSlashing: vi.fn(), + getSlashingsAndExits: vi.fn(), + }; + }); + + const AggregatedAttestationPool = vi.fn().mockImplementation(() => { + return { + getAttestationsForBlock: vi.fn(), + }; + }); + + return { + ...mod, + OpPool, + AggregatedAttestationPool, + }; +}); + +vi.mock("../../src/chain/chain.js", async (importActual) => { + const mod = await importActual(); const BeaconChain = vi.fn().mockImplementation(({clock, genesisTime, config}: MockedBeaconChainOptions) => { + const logger = getMockedLogger(); + return { config, opts: {}, @@ -61,15 +117,12 @@ vi.mock("../../src/chain/index.js", async (requireActual) => { currentSlotWithGossipDisparity: undefined, isCurrentSlotGivenGossipDisparity: vi.fn(), }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - forkChoice: new ForkChoice(), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - executionEngine: new ExecutionEngineHttp(), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - executionBuilder: new ExecutionBuilderHttp(), + forkChoice: getMockedForkChoice(), + executionEngine: { + notifyForkchoiceUpdate: vi.fn(), + getPayload: vi.fn(), + }, + executionBuilder: {}, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error eth1: new Eth1ForBlockProduction(), @@ -90,7 +143,7 @@ vi.mock("../../src/chain/index.js", async (requireActual) => { processBlock: vi.fn(), regenStateForAttestationVerification: vi.fn(), close: vi.fn(), - logger: getMockedLogger(), + logger, regen: new QueuedStateRegenerator({} as any), lightClientServer: new LightClientServer({} as any, {} as any), bls: { @@ -99,7 +152,7 @@ vi.mock("../../src/chain/index.js", async (requireActual) => { close: vi.fn().mockResolvedValue(true), canAcceptWork: vi.fn().mockReturnValue(true), }, - emitter: new mod.ChainEventEmitter(), + emitter: new ChainEventEmitter(), }; }); @@ -125,3 +178,14 @@ export function getMockedBeaconChain(opts?: Partial): config: config ?? defaultConfig, }) as MockedBeaconChain; } + +export type MockedForkChoice = Mocked; + +export function getMockedForkChoice(): MockedForkChoice { + // ForkChoice package is mocked globally + return vi.mocked(new ForkChoice({} as any, {} as any, {} as any, {} as any)); +} + +// To avoid loading the package in test while mocked, exporting frequently used types and constants +export type {ProtoBlock}; +export {EpochDifference}; diff --git a/packages/beacon-node/test/mocks/mockedBeaconDb.ts b/packages/beacon-node/test/mocks/mockedBeaconDb.ts new file mode 100644 index 000000000000..4f5f494a0f40 --- /dev/null +++ b/packages/beacon-node/test/mocks/mockedBeaconDb.ts @@ -0,0 +1,75 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import {vi, Mocked} from "vitest"; +import {config as minimalConfig} from "@lodestar/config/default"; +import { + AttesterSlashingRepository, + BlockArchiveRepository, + BlockRepository, + DepositEventRepository, + DepositDataRootRepository, + Eth1DataRepository, + ProposerSlashingRepository, + StateArchiveRepository, + VoluntaryExitRepository, + BLSToExecutionChangeRepository, + BlobSidecarsRepository, + BlobSidecarsArchiveRepository, +} from "../../src/db/repositories/index.js"; +import {BeaconDb} from "../../src/db/index.js"; + +export type MockedBeaconDb = Mocked & { + block: Mocked; + blockArchive: Mocked; + + blobSidecars: Mocked; + blobSidecarsArchive: Mocked; + + stateArchive: Mocked; + + voluntaryExit: Mocked; + blsToExecutionChange: Mocked; + proposerSlashing: Mocked; + attesterSlashing: Mocked; + depositEvent: Mocked; + + depositDataRoot: Mocked; + eth1Data: Mocked; +}; + +vi.mock("../../src/db/repositories/index.js"); + +vi.mock("../../src/db/index.js", async (importActual) => { + const mod = await importActual(); + + const mockedBeaconDb = vi.fn().mockImplementation(() => { + return { + block: vi.mocked(new BlockRepository({} as any, {} as any)), + blockArchive: vi.mocked(new BlockArchiveRepository({} as any, {} as any)), + stateArchive: vi.mocked(new StateArchiveRepository({} as any, {} as any)), + + voluntaryExit: vi.mocked(new VoluntaryExitRepository({} as any, {} as any)), + blsToExecutionChange: vi.mocked(new BLSToExecutionChangeRepository({} as any, {} as any)), + proposerSlashing: vi.mocked(new ProposerSlashingRepository({} as any, {} as any)), + attesterSlashing: vi.mocked(new AttesterSlashingRepository({} as any, {} as any)), + depositEvent: vi.mocked(new DepositEventRepository({} as any, {} as any)), + + depositDataRoot: vi.mocked(new DepositDataRootRepository({} as any, {} as any)), + eth1Data: vi.mocked(new Eth1DataRepository({} as any, {} as any)), + + blobSidecars: vi.mocked(new BlobSidecarsRepository({} as any, {} as any)), + blobSidecarsArchive: vi.mocked(new BlobSidecarsArchiveRepository({} as any, {} as any)), + }; + }); + + return { + ...mod, + // eslint-disable-next-line @typescript-eslint/naming-convention + BeaconDb: mockedBeaconDb, + }; +}); + +export function getMockedBeaconDb(): MockedBeaconDb { + return new BeaconDb(minimalConfig, {} as any) as MockedBeaconDb; +} + +vi.resetModules(); diff --git a/packages/beacon-node/test/__mocks__/mockedBls.ts b/packages/beacon-node/test/mocks/mockedBls.ts similarity index 100% rename from packages/beacon-node/test/__mocks__/mockedBls.ts rename to packages/beacon-node/test/mocks/mockedBls.ts diff --git a/packages/beacon-node/test/mocks/mockedNetwork.ts b/packages/beacon-node/test/mocks/mockedNetwork.ts new file mode 100644 index 000000000000..ddf70aa1b5aa --- /dev/null +++ b/packages/beacon-node/test/mocks/mockedNetwork.ts @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import {vi, Mocked} from "vitest"; +import {Network, INetwork} from "../../src/network/index.js"; + +vi.mock("../../src/network/index.js", async (importActual) => { + const mod = await importActual(); + + const Network = vi.fn().mockImplementation(() => { + return {}; + }); + + return { + ...mod, + Network, + }; +}); + +export type MockedNetwork = Mocked; + +export function getMockedNetwork(): MockedNetwork { + return new Network({} as any) as unknown as MockedNetwork; +} diff --git a/packages/beacon-node/test/mocks/regenMocks.ts b/packages/beacon-node/test/mocks/regenMocks.ts new file mode 100644 index 000000000000..39f7fa382760 --- /dev/null +++ b/packages/beacon-node/test/mocks/regenMocks.ts @@ -0,0 +1,10 @@ +import {vi, Mocked} from "vitest"; +import {QueuedStateRegenerator} from "../../src/chain/regen/index.js"; + +export type MockedQueuedStateRegenerator = Mocked; + +vi.mock("../../src/chain/regen/index.js"); + +export function getMockedQueuedStateRegenerator(): MockedQueuedStateRegenerator { + return vi.mocked(new QueuedStateRegenerator({} as any)); +} diff --git a/packages/beacon-node/test/mocks/shufflingMock.ts b/packages/beacon-node/test/mocks/shufflingMock.ts new file mode 100644 index 000000000000..76482f760872 --- /dev/null +++ b/packages/beacon-node/test/mocks/shufflingMock.ts @@ -0,0 +1,10 @@ +import {vi, Mocked} from "vitest"; +import {ShufflingCache} from "../../src/chain/shufflingCache.js"; + +export type MockedShufflingCache = Mocked; + +vi.mock("../../src/chain/shufflingCache.js"); + +export function getMockedShufflingCache(): MockedShufflingCache { + return vi.mocked(new ShufflingCache({} as any)); +} diff --git a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts index 309a5c29a6b0..a7de0653c16a 100644 --- a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts @@ -1,4 +1,3 @@ -import sinon from "sinon"; import {itBench} from "@dapplion/benchmark"; import {expect} from "chai"; import {BitArray, toHexString} from "@chainsafe/ssz"; @@ -29,7 +28,6 @@ describe("getAttestationsForBlock", () => { let originalState: CachedBeaconStateAltair; let protoArray: ProtoArray; let forkchoice: ForkChoice; - const sandbox = sinon.createSandbox(); before(function () { this.timeout(2 * 60 * 1000); // Generating the states for the first time is very slow @@ -121,10 +119,6 @@ describe("getAttestationsForBlock", () => { forkchoice = new ForkChoice(originalState.config, fcStore, protoArray); }); - after(() => { - sandbox.restore(); - }); - itBench({ id: "getAttestationsForBlock", beforeEach: () => getAggregatedAttestationPool(originalState), diff --git a/packages/beacon-node/test/perf/network/peers/enrSubnetsDeserialize.test.ts b/packages/beacon-node/test/perf/network/peers/enrSubnetsDeserialize.test.ts index f8ed571f9622..2507c43bcc9c 100644 --- a/packages/beacon-node/test/perf/network/peers/enrSubnetsDeserialize.test.ts +++ b/packages/beacon-node/test/perf/network/peers/enrSubnetsDeserialize.test.ts @@ -6,7 +6,7 @@ import {deserializeEnrSubnets} from "../../../../src/network/peers/utils/enrSubn /** * Ideally we want to sleep between requests to test the prune. - * But adding sinon mock timer here make it impossible to benchmark. + * But adding mock timer here make it impossible to benchmark. */ describe("network / peers / deserializeEnrSubnets", () => { const attnets = Buffer.from("feffb7f7fdfffefd", "hex"); diff --git a/packages/beacon-node/test/scripts/el-interop/gethdocker/README.md b/packages/beacon-node/test/scripts/el-interop/gethdocker/README.md index df4b56f4368a..6525de57d30f 100644 --- a/packages/beacon-node/test/scripts/el-interop/gethdocker/README.md +++ b/packages/beacon-node/test/scripts/el-interop/gethdocker/README.md @@ -12,5 +12,5 @@ docker pull ethereum/client-go:latest ```bash cd packages/lodestar -EL_BINARY_DIR=ethereum/client-go:latest EL_SCRIPT_DIR=gethdocker ETH_PORT=8545 ENGINE_PORT=8551 TX_SCENARIOS=simple yarn mocha test/sim/merge-interop.test.ts +EL_BINARY_DIR=ethereum/client-go:latest EL_SCRIPT_DIR=gethdocker ETH_PORT=8545 ENGINE_PORT=8551 TX_SCENARIOS=simple yarn vitest --run test/sim/merge-interop.test.ts ``` diff --git a/packages/beacon-node/test/setup.ts b/packages/beacon-node/test/setup.ts deleted file mode 100644 index b83e6cb78511..000000000000 --- a/packages/beacon-node/test/setup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import sinonChai from "sinon-chai"; - -chai.use(chaiAsPromised); -chai.use(sinonChai); diff --git a/packages/beacon-node/test/sim/4844-interop.test.ts b/packages/beacon-node/test/sim/4844-interop.test.ts index 014339a3d2d8..d6de49e32eff 100644 --- a/packages/beacon-node/test/sim/4844-interop.test.ts +++ b/packages/beacon-node/test/sim/4844-interop.test.ts @@ -1,5 +1,5 @@ import fs from "node:fs"; -import {Context} from "mocha"; +import {describe, it, vi, afterAll, afterEach} from "vitest"; import {fromHexString} from "@chainsafe/ssz"; import {LogLevel, sleep} from "@lodestar/utils"; import {TimestampFormatCode} from "@lodestar/logger"; @@ -24,7 +24,7 @@ import {logFilesDir} from "./params.js"; import {shell} from "./shell.js"; // NOTE: How to run -// DEV_RUN=true EL_BINARY_DIR=g11tech/ethereumjs:devnet6-32aaac EL_SCRIPT_DIR=ethereumjsdocker yarn mocha test/sim/4844-interop.test.ts +// DEV_RUN=true EL_BINARY_DIR=g11tech/ethereumjs:devnet6-32aaac EL_SCRIPT_DIR=ethereumjsdocker yarn vitest --run test/sim/4844-interop.test.ts // ``` /* eslint-disable no-console, @typescript-eslint/naming-convention */ @@ -37,7 +37,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { `EL ENV must be provided, EL_BINARY_DIR: ${process.env.EL_BINARY_DIR}, EL_SCRIPT_DIR: ${process.env.EL_SCRIPT_DIR}` ); } - this.timeout("10min"); + vi.setConfig({testTimeout: 1000 * 60 * 10, hookTimeout: 1000 * 60 * 10}); const dataPath = fs.mkdtempSync("lodestar-test-4844"); const elSetupConfig = { @@ -52,7 +52,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { }; const controller = new AbortController(); - after(async () => { + afterAll(async () => { controller?.abort(); await shell(`sudo rm -rf ${dataPath}`); }); @@ -65,6 +65,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); + // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -74,17 +75,22 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); afterEachCallbacks.push(() => tearDownCallBack()); - await runNodeWithEL.bind(this)({ + await runNodeWithEL({ elClient, denebEpoch: 0, testName: "post-merge", }); }); - async function runNodeWithEL( - this: Context, - {elClient, denebEpoch, testName}: {elClient: ELClient; denebEpoch: Epoch; testName: string} - ): Promise { + async function runNodeWithEL({ + elClient, + denebEpoch, + testName, + }: { + elClient: ELClient; + denebEpoch: Epoch; + testName: string; + }): Promise { const {genesisBlockHash, ttd, engineRpcUrl, ethRpcUrl} = elClient; const validatorClientCount = 1; const validatorsPerClient = 8; @@ -112,8 +118,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { ((epochsOfMargin + 10 * expectedEpochsToFinish) * SLOTS_PER_EPOCH + genesisSlotsDelay) * testParams.SECONDS_PER_SLOT * 1000; - - this.timeout(timeout + 2 * timeoutSetupMargin); + vi.setConfig({testTimeout: timeout + 2 * timeoutSetupMargin}); const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; diff --git a/packages/beacon-node/test/sim/merge-interop.test.ts b/packages/beacon-node/test/sim/merge-interop.test.ts index a9fa10ab2208..9467c53831c8 100644 --- a/packages/beacon-node/test/sim/merge-interop.test.ts +++ b/packages/beacon-node/test/sim/merge-interop.test.ts @@ -1,5 +1,5 @@ import fs from "node:fs"; -import {Context} from "mocha"; +import {describe, it, afterAll, afterEach, vi} from "vitest"; import {fromHexString} from "@chainsafe/ssz"; import {isExecutionStateType, isMergeTransitionComplete} from "@lodestar/state-transition"; import {LogLevel, sleep} from "@lodestar/utils"; @@ -39,7 +39,7 @@ import {shell} from "./shell.js"; // ``` // $ EL_BINARY_DIR=/home/lion/Code/eth2.0/merge-interop/go-ethereum/build/bin \ // EL_SCRIPT_DIR=geth ETH_PORT=8545 ENGINE_PORT=8551 TX_SCENARIOS=simple \ -// ../../node_modules/.bin/mocha test/sim/merge.test.ts +// ../../node_modules/.bin/vitest --run test/sim/merge.test.ts // ``` /* eslint-disable no-console, @typescript-eslint/naming-convention, quotes */ @@ -58,7 +58,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { `EL ENV must be provided, EL_BINARY_DIR: ${process.env.EL_BINARY_DIR}, EL_SCRIPT_DIR: ${process.env.EL_SCRIPT_DIR}` ); } - this.timeout("10min"); + vi.setConfig({testTimeout: 10 * 60 * 1000}); const dataPath = fs.mkdtempSync("lodestar-test-merge-interop"); const elSetupConfig = { @@ -73,7 +73,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { }; const controller = new AbortController(); - after(async () => { + afterAll(async () => { controller?.abort(); await shell(`sudo rm -rf ${dataPath}`); }); @@ -86,6 +86,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); + // eslint-disable-next-line vitest/expect-expect it("Send stub payloads to EL", async () => { const {elClient, tearDownCallBack} = await runEL( {...elSetupConfig, mode: ELStartMode.PostMerge}, @@ -202,6 +203,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { */ }); + // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -211,13 +213,14 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); afterEachCallbacks.push(() => tearDownCallBack()); - await runNodeWithEL.bind(this)({ + await runNodeWithEL({ elClient, bellatrixEpoch: 0, testName: "post-merge", }); }); + // eslint-disable-next-line vitest/expect-expect it("Pre-merge, run for a few blocks", async function () { console.log("\n\nPre-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -227,17 +230,22 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); afterEachCallbacks.push(() => tearDownCallBack()); - await runNodeWithEL.bind(this)({ + await runNodeWithEL({ elClient, bellatrixEpoch: 1, testName: "pre-merge", }); }); - async function runNodeWithEL( - this: Context, - {elClient, bellatrixEpoch, testName}: {elClient: ELClient; bellatrixEpoch: Epoch; testName: string} - ): Promise { + async function runNodeWithEL({ + elClient, + bellatrixEpoch, + testName, + }: { + elClient: ELClient; + bellatrixEpoch: Epoch; + testName: string; + }): Promise { const {genesisBlockHash, ttd, engineRpcUrl, ethRpcUrl} = elClient; const validatorClientCount = 1; const validatorsPerClient = 32; @@ -261,7 +269,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { testParams.SECONDS_PER_SLOT * 1000; - this.timeout(timeout + 2 * timeoutSetupMargin); + vi.setConfig({testTimeout: timeout + 2 * timeoutSetupMargin}); const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; diff --git a/packages/beacon-node/test/sim/mergemock.test.ts b/packages/beacon-node/test/sim/mergemock.test.ts index d9492723599d..97a9d9f2aaf7 100644 --- a/packages/beacon-node/test/sim/mergemock.test.ts +++ b/packages/beacon-node/test/sim/mergemock.test.ts @@ -1,5 +1,5 @@ import fs from "node:fs"; -import {Context} from "mocha"; +import {describe, it, afterAll, afterEach, vi} from "vitest"; import {fromHexString, toHexString} from "@chainsafe/ssz"; import {LogLevel, sleep} from "@lodestar/utils"; import {TimestampFormatCode} from "@lodestar/logger"; @@ -22,7 +22,7 @@ import {logFilesDir} from "./params.js"; import {shell} from "./shell.js"; // NOTE: How to run -// EL_BINARY_DIR=g11tech/mergemock:latest EL_SCRIPT_DIR=mergemock LODESTAR_PRESET=mainnet ETH_PORT=8661 ENGINE_PORT=8551 yarn mocha test/sim/mergemock.test.ts +// EL_BINARY_DIR=g11tech/mergemock:latest EL_SCRIPT_DIR=mergemock LODESTAR_PRESET=mainnet ETH_PORT=8661 ENGINE_PORT=8551 yarn vitest --run test/sim/mergemock.test.ts // ``` /* eslint-disable no-console, @typescript-eslint/naming-convention */ @@ -35,7 +35,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { `EL ENV must be provided, EL_BINARY_DIR: ${process.env.EL_BINARY_DIR}, EL_SCRIPT_DIR: ${process.env.EL_SCRIPT_DIR}` ); } - this.timeout("10min"); + vi.setConfig({testTimeout: 10 * 60 * 1000}); const dataPath = fs.mkdtempSync("lodestar-test-mergemock"); const elSetupConfig = { @@ -50,7 +50,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { }; const controller = new AbortController(); - after(async () => { + afterAll(async () => { controller?.abort(); await shell(`sudo rm -rf ${dataPath}`); }); @@ -64,6 +64,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { }); for (const useProduceBlockV3 of [false, true]) { + // eslint-disable-next-line vitest/expect-expect it(`Test builder with useProduceBlockV3=${useProduceBlockV3}`, async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -73,7 +74,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); afterEachCallbacks.push(() => tearDownCallBack()); - await runNodeWithEL.bind(this)({ + await runNodeWithEL({ elClient, bellatrixEpoch: 0, testName: "post-merge", @@ -84,10 +85,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { type RunOpts = {elClient: ELClient; bellatrixEpoch: Epoch; testName: string; useProduceBlockV3: boolean}; - async function runNodeWithEL( - this: Context, - {elClient, bellatrixEpoch, testName, useProduceBlockV3}: RunOpts - ): Promise { + async function runNodeWithEL({elClient, bellatrixEpoch, testName, useProduceBlockV3}: RunOpts): Promise { const {genesisBlockHash, ttd, engineRpcUrl, ethRpcUrl} = elClient; const validatorClientCount = 1; const validatorsPerClient = 32; @@ -123,7 +121,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { testParams.SECONDS_PER_SLOT * 1000; - this.timeout(timeout + 2 * timeoutSetupMargin); + vi.setConfig({testTimeout: timeout + 2 * timeoutSetupMargin}); const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; diff --git a/packages/beacon-node/test/sim/withdrawal-interop.test.ts b/packages/beacon-node/test/sim/withdrawal-interop.test.ts index b828382ad247..6fdd4fd5a0ce 100644 --- a/packages/beacon-node/test/sim/withdrawal-interop.test.ts +++ b/packages/beacon-node/test/sim/withdrawal-interop.test.ts @@ -1,5 +1,5 @@ import fs from "node:fs"; -import {Context} from "mocha"; +import {describe, it, afterAll, afterEach, vi} from "vitest"; import {fromHexString, toHexString} from "@chainsafe/ssz"; import {LogLevel, sleep} from "@lodestar/utils"; import {TimestampFormatCode} from "@lodestar/logger"; @@ -27,7 +27,7 @@ import {logFilesDir} from "./params.js"; import {shell} from "./shell.js"; // NOTE: How to run -// EL_BINARY_DIR=g11tech/geth:withdrawalsfeb8 EL_SCRIPT_DIR=gethdocker yarn mocha test/sim/withdrawal-interop.test.ts +// EL_BINARY_DIR=g11tech/geth:withdrawalsfeb8 EL_SCRIPT_DIR=gethdocker yarn vitest --run test/sim/withdrawal-interop.test.ts // ``` /* eslint-disable no-console, @typescript-eslint/naming-convention */ @@ -42,7 +42,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { `EL ENV must be provided, EL_BINARY_DIR: ${process.env.EL_BINARY_DIR}, EL_SCRIPT_DIR: ${process.env.EL_SCRIPT_DIR}` ); } - this.timeout("10min"); + vi.setConfig({testTimeout: 10 * 60 * 1000}); const dataPath = fs.mkdtempSync("lodestar-test-withdrawal"); const elSetupConfig = { @@ -57,7 +57,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { }; const controller = new AbortController(); - after(async () => { + afterAll(async () => { controller?.abort(); await shell(`sudo rm -rf ${dataPath}`); }); @@ -70,6 +70,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); + // eslint-disable-next-line vitest/expect-expect it("Send stub payloads to EL", async () => { const {elClient, tearDownCallBack} = await runEL( {...elSetupConfig, mode: ELStartMode.PostMerge, genesisTemplate: "genesisPostWithdraw.tmpl"}, @@ -184,6 +185,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); }); + // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -193,17 +195,22 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); afterEachCallbacks.push(() => tearDownCallBack()); - await runNodeWithEL.bind(this)({ + await runNodeWithEL({ elClient, capellaEpoch: 0, testName: "post-merge", }); }); - async function runNodeWithEL( - this: Context, - {elClient, capellaEpoch, testName}: {elClient: ELClient; capellaEpoch: Epoch; testName: string} - ): Promise { + async function runNodeWithEL({ + elClient, + capellaEpoch, + testName, + }: { + elClient: ELClient; + capellaEpoch: Epoch; + testName: string; + }): Promise { const {genesisBlockHash, ttd, engineRpcUrl} = elClient; const validatorClientCount = 1; const validatorsPerClient = 32; @@ -229,7 +236,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { testParams.SECONDS_PER_SLOT * 1000; - this.timeout(timeout + 2 * timeoutSetupMargin); + vi.setConfig({testTimeout: timeout + 2 * timeoutSetupMargin}); const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; diff --git a/packages/beacon-node/test/spec/bls/index.test.ts b/packages/beacon-node/test/spec/bls/index.test.ts index b581b8681870..b781685432e6 100644 --- a/packages/beacon-node/test/spec/bls/index.test.ts +++ b/packages/beacon-node/test/spec/bls/index.test.ts @@ -35,20 +35,14 @@ for (const fnName of readdirSyncSpec(blsSpecTests.outputDir)) { const fnTestDirpath = path.join(blsSpecTests.outputDir, fnName); for (const testName of readdirSyncSpec(fnTestDirpath)) { - // TODO: Will be removed when we remove chai/mocha eslint rules - // eslint-disable-next-line mocha/handle-done-callback it(`${fnName}/${testName}`, function (context) { if (fn === "skip") { - // TODO: Will be removed when we remove chai/mocha eslint rules - // eslint-disable-next-line mocha/no-nested-tests context.skip(); return; } // Do not manually skip tests here, do it in the top of the file if (skippedTestNames.includes(testName)) { - // TODO: Will be removed when we remove chai/mocha eslint rules - // eslint-disable-next-line mocha/no-nested-tests context.skip(); return; } @@ -58,10 +52,10 @@ for (const fnName of readdirSyncSpec(blsSpecTests.outputDir)) { // Test format: https://github.com/ethereum/bls12-381-tests if (testData.output === null) { // Expect failure - expect(() => fn(testData.input) as never).to.throw(); + expect(() => fn(testData.input) as never).toThrow(); } else { // Expect success - expect(fn(testData.input)).to.deep.equals(testData.output); + expect(fn(testData.input)).toEqual(testData.output); } }); } diff --git a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts index 951761b9b743..a244762143f3 100644 --- a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts +++ b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts @@ -71,7 +71,7 @@ const epochProcessing = if (testcase.post === undefined) { // If post.ssz_snappy is not value, the sub-transition processing is aborted // https://github.com/ethereum/consensus-specs/blob/dev/tests/formats/epoch_processing/README.md#postssz_snappy - expect(() => epochTransitionFn(state, epochTransitionCache)).to.throw(); + expect(() => epochTransitionFn(state, epochTransitionCache)).toThrow(); } else { epochTransitionFn(state, epochTransitionCache); } diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index 665e395222f9..b0ad63a68205 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -20,8 +20,8 @@ import {getExecutionEngineFromBackend} from "../../../src/execution/index.js"; import {ExecutionPayloadStatus} from "../../../src/execution/engine/interface.js"; import {ExecutionEngineMockBackend} from "../../../src/execution/engine/mock.js"; import {defaultChainOptions} from "../../../src/chain/options.js"; -import {getStubbedBeaconDb} from "../../utils/mocks/db.js"; -import {ClockStopped} from "../../utils/mocks/clock.js"; +import {getMockedBeaconDb} from "../../mocks/mockedBeaconDb.js"; +import {ClockStopped} from "../../mocks/clock.js"; import { getBlockInput, AttestationImportOpt, @@ -99,7 +99,7 @@ const forkChoiceTest = }, { config: createBeaconConfig(config, state.genesisValidatorsRoot), - db: getStubbedBeaconDb(), + db: getMockedBeaconDb(), logger, // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, @@ -268,13 +268,13 @@ const forkChoiceTest = const proposerBootRoot = (chain.forkChoice as ForkChoice).getProposerBoostRoot(); if (step.checks.head !== undefined) { - expect({slot: head.slot, root: head.blockRoot}).deep.equals( + expect({slot: head.slot, root: head.blockRoot}).toEqualWithMessage( {slot: bnToNum(step.checks.head.slot), root: step.checks.head.root}, `Invalid head at step ${i}` ); } if (step.checks.proposer_boost_root !== undefined) { - expect(proposerBootRoot).to.be.equal( + expect(proposerBootRoot).toEqualWithMessage( step.checks.proposer_boost_root, `Invalid proposer boost root at step ${i}` ); @@ -283,18 +283,18 @@ const forkChoiceTest = // Compare in slots because proposer boost steps doesn't always come on // slot boundary. if (step.checks.time !== undefined && step.checks.time > 0) - expect(chain.forkChoice.getTime()).to.be.equal( + expect(chain.forkChoice.getTime()).toEqualWithMessage( Math.floor(bnToNum(step.checks.time) / config.SECONDS_PER_SLOT), `Invalid forkchoice time at step ${i}` ); if (step.checks.justified_checkpoint) { - expect(toSpecTestCheckpoint(chain.forkChoice.getJustifiedCheckpoint())).to.be.deep.equal( + expect(toSpecTestCheckpoint(chain.forkChoice.getJustifiedCheckpoint())).toEqualWithMessage( step.checks.justified_checkpoint, `Invalid justified checkpoint at step ${i}` ); } if (step.checks.finalized_checkpoint) { - expect(toSpecTestCheckpoint(chain.forkChoice.getFinalizedCheckpoint())).to.be.deep.equal( + expect(toSpecTestCheckpoint(chain.forkChoice.getFinalizedCheckpoint())).toEqualWithMessage( step.checks.finalized_checkpoint, `Invalid finalized checkpoint at step ${i}` ); diff --git a/packages/beacon-node/test/spec/presets/genesis.test.ts b/packages/beacon-node/test/spec/presets/genesis.test.ts index 0b707f509428..ba3351a2103c 100644 --- a/packages/beacon-node/test/spec/presets/genesis.test.ts +++ b/packages/beacon-node/test/spec/presets/genesis.test.ts @@ -109,7 +109,7 @@ const genesisValidity: TestRunnerFn = (fork) = }, getExpected: (testCase) => testCase.is_valid, expectFunc: (testCase, expected, actual) => { - expect(actual).to.be.equal(expected, "isValidGenesisState is not" + expected); + expect(actual).toEqualWithMessage(expected, "isValidGenesisState is not" + expected); }, }, }; diff --git a/packages/beacon-node/test/spec/presets/merkle.test.ts b/packages/beacon-node/test/spec/presets/merkle.test.ts index a711d9ce66ac..d3f6890527e9 100644 --- a/packages/beacon-node/test/spec/presets/merkle.test.ts +++ b/packages/beacon-node/test/spec/presets/merkle.test.ts @@ -23,7 +23,7 @@ const merkle: TestRunnerFn = (fork) => { const leafIndex = Number(specTestProof.leaf_index); const depth = Math.floor(Math.log2(leafIndex)); const verified = verifyMerkleBranch(leaf, branch, depth, leafIndex % 2 ** depth, stateRoot); - expect(verified).to.equal(true, "invalid merkle branch"); + expect(verified).toEqualWithMessage(true, "invalid merkle branch"); const lodestarProof = new Tree(state.node).getProof({ gindex: specTestProof.leaf_index, @@ -48,7 +48,7 @@ const merkle: TestRunnerFn = (fork) => { timeout: 10000, getExpected: (testCase) => testCase.proof, expectFunc: (testCase, expected, actual) => { - expect(actual).to.be.deep.equal(expected, "incorrect proof"); + expect(actual).toEqualWithMessage(expected, "incorrect proof"); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts }, diff --git a/packages/beacon-node/test/spec/presets/rewards.test.ts b/packages/beacon-node/test/spec/presets/rewards.test.ts index 635d658857b1..426245242d84 100644 --- a/packages/beacon-node/test/spec/presets/rewards.test.ts +++ b/packages/beacon-node/test/spec/presets/rewards.test.ts @@ -58,7 +58,7 @@ const rewards: TestRunnerFn = (fork) => { testCase.inactivity_penalty_deltas, ]), expectFunc: (testCase, expected, actual) => { - expect(actual).to.deep.equal(expected); + expect(actual).toEqual(expected); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts }, diff --git a/packages/beacon-node/test/spec/presets/ssz_static.test.ts b/packages/beacon-node/test/spec/presets/ssz_static.test.ts index a23a7d388f55..e4d55d010dc6 100644 --- a/packages/beacon-node/test/spec/presets/ssz_static.test.ts +++ b/packages/beacon-node/test/spec/presets/ssz_static.test.ts @@ -56,6 +56,7 @@ const sszStatic = for (const testCase of fs.readdirSync(testSuiteDirpath)) { // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts + // eslint-disable-next-line vitest/consistent-test-it it(testCase, function () { // Mainnet must deal with big full states and hash each one multiple times if (ACTIVE_PRESET === "mainnet") { diff --git a/packages/beacon-node/test/spec/utils/runValidSszTest.ts b/packages/beacon-node/test/spec/utils/runValidSszTest.ts index 7dedd0983e3b..e5f249ab5257 100644 --- a/packages/beacon-node/test/spec/utils/runValidSszTest.ts +++ b/packages/beacon-node/test/spec/utils/runValidSszTest.ts @@ -76,7 +76,7 @@ export function runValidSszTest(type: Type, testData: ValidTestCaseData // To print the chunk roots of a type value // - // $ RENDER_ROOTS=true ONLY_ID="4 arrays" ../../node_modules/.bin/mocha test/unit/byType/vector/valid.test.ts + // $ RENDER_ROOTS=true ONLY_ID="4 arrays" ../../node_modules/.bin/vitest test/unit/byType/vector/valid.test.ts // // 0x0000000000000000000000000000000000000000000000000000000000000000 if (process.env.RENDER_ROOTS) { @@ -103,7 +103,7 @@ export function runValidSszTest(type: Type, testData: ValidTestCaseData // To print a tree a single test you are debugging do // - // $ RENDER_TREE=true ONLY_ID="4 arrays" ../../node_modules/.bin/mocha test/unit/byType/vector/valid.test.ts + // $ RENDER_TREE=true ONLY_ID="4 arrays" ../../node_modules/.bin/vitest --run test/unit/byType/vector/valid.test.ts // // '1000' => '0x0000000000000000000000000000000000000000000000000000000000000000', // '1001' => '0x0000000000000000000000000000000000000000000000000000000000000000', diff --git a/packages/beacon-node/test/unit-mainnet/network/gossip/scoringParameters.test.ts b/packages/beacon-node/test/unit-mainnet/network/gossip/scoringParameters.test.ts index 3b84bba01f92..6805f00ced1b 100644 --- a/packages/beacon-node/test/unit-mainnet/network/gossip/scoringParameters.test.ts +++ b/packages/beacon-node/test/unit-mainnet/network/gossip/scoringParameters.test.ts @@ -1,4 +1,4 @@ -import {expect} from "chai"; +import {describe, it, expect} from "vitest"; import {TopicScoreParams} from "@chainsafe/libp2p-gossipsub/score"; import {ATTESTATION_SUBNET_COUNT, ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; import {createBeaconConfig} from "@lodestar/config"; @@ -26,11 +26,11 @@ describe("computeGossipPeerScoreParams", function () { currentSlot: 0, currentEpoch: 0, }; - expect(gossipScoreThresholds.gossipThreshold).to.be.equal(-4000); - expect(gossipScoreThresholds.publishThreshold).to.be.equal(-8000); - expect(gossipScoreThresholds.graylistThreshold).to.be.equal(-16000); - expect(gossipScoreThresholds.acceptPXThreshold).to.be.equal(100); - expect(gossipScoreThresholds.opportunisticGraftThreshold).to.be.equal(5); + expect(gossipScoreThresholds.gossipThreshold).toEqual(-4000); + expect(gossipScoreThresholds.publishThreshold).toEqual(-8000); + expect(gossipScoreThresholds.graylistThreshold).toEqual(-16000); + expect(gossipScoreThresholds.acceptPXThreshold).toEqual(100); + expect(gossipScoreThresholds.opportunisticGraftThreshold).toEqual(5); const params = computeGossipPeerScoreParams({config, eth2Context}); const allTopics = params.topics; if (!allTopics) { @@ -49,11 +49,11 @@ describe("computeGossipPeerScoreParams", function () { currentSlot: 10_000, currentEpoch: Math.floor(10_000 / SLOTS_PER_EPOCH), }; - expect(gossipScoreThresholds.gossipThreshold).to.be.equal(-4000); - expect(gossipScoreThresholds.publishThreshold).to.be.equal(-8000); - expect(gossipScoreThresholds.graylistThreshold).to.be.equal(-16000); - expect(gossipScoreThresholds.acceptPXThreshold).to.be.equal(100); - expect(gossipScoreThresholds.opportunisticGraftThreshold).to.be.equal(5); + expect(gossipScoreThresholds.gossipThreshold).toEqual(-4000); + expect(gossipScoreThresholds.publishThreshold).toEqual(-8000); + expect(gossipScoreThresholds.graylistThreshold).toEqual(-16000); + expect(gossipScoreThresholds.acceptPXThreshold).toEqual(100); + expect(gossipScoreThresholds.opportunisticGraftThreshold).toEqual(5); const params = computeGossipPeerScoreParams({config, eth2Context}); const allTopics = params.topics; if (!allTopics) { @@ -73,10 +73,10 @@ describe("computeGossipPeerScoreParams", function () { }); const params = topics[topicString]; assertMessageRatePenaltiesDisabled(params); - expect(params.topicWeight).to.be.equal(0.05); + expect(params.topicWeight).toEqual(0.05); expect(params.timeInMeshWeight).closeTo(0.03333, TOLERANCE); - expect(params.timeInMeshQuantum).to.be.equal(12 * 1000); - expect(params.timeInMeshCap).to.be.equal(300); + expect(params.timeInMeshQuantum).toEqual(12 * 1000); + expect(params.timeInMeshCap).toEqual(300); expect(params.firstMessageDeliveriesWeight).closeTo(1.8407, TOLERANCE); expect(params.firstMessageDeliveriesDecay).closeTo(0.99856, TOLERANCE); expect(params.firstMessageDeliveriesCap).closeTo(21.73035, TOLERANCE); @@ -99,10 +99,10 @@ describe("computeGossipPeerScoreParams", function () { function validateSlashingTopicScoreParams(params: TopicScoreParams): void { assertMessageRatePenaltiesDisabled(params); - expect(params.topicWeight).to.be.equal(0.05); + expect(params.topicWeight).toEqual(0.05); expect(params.timeInMeshWeight).closeTo(0.03333, TOLERANCE); - expect(params.timeInMeshQuantum).to.be.equal(12 * 1000); - expect(params.timeInMeshCap).to.be.equal(300.0); + expect(params.timeInMeshQuantum).toEqual(12 * 1000); + expect(params.timeInMeshCap).toEqual(300.0); expect(params.firstMessageDeliveriesWeight).closeTo(36.81486, TOLERANCE); expect(params.firstMessageDeliveriesDecay).closeTo(0.998561, TOLERANCE); expect(params.firstMessageDeliveriesCap).closeTo(1.08652, TOLERANCE); @@ -117,10 +117,10 @@ describe("computeGossipPeerScoreParams", function () { }); const params = topics[topicString]; - expect(params.topicWeight).to.be.equal(0.5); + expect(params.topicWeight).toEqual(0.5); expect(params.timeInMeshWeight).closeTo(0.03333, TOLERANCE); - expect(params.timeInMeshQuantum).to.be.equal(12 * 1000); - expect(params.timeInMeshCap).to.be.equal(300.0); + expect(params.timeInMeshQuantum).toEqual(12 * 1000); + expect(params.timeInMeshCap).toEqual(300.0); expect(params.firstMessageDeliveriesWeight).closeTo(0.33509, TOLERANCE); expect(params.firstMessageDeliveriesDecay).closeTo(0.86596, TOLERANCE); expect(params.firstMessageDeliveriesCap).closeTo(119.3712, TOLERANCE); @@ -130,8 +130,8 @@ describe("computeGossipPeerScoreParams", function () { // Check message rate penalty params expect(params.meshMessageDeliveriesDecay).closeTo(0.930572, TOLERANCE); expect(params.meshMessageDeliveriesCap).closeTo(68.6255, TOLERANCE); - expect(params.meshMessageDeliveriesActivation).to.be.equal(384 * 1000); - expect(params.meshMessageDeliveriesWindow).to.be.equal(12 * 1000); + expect(params.meshMessageDeliveriesActivation).toEqual(384 * 1000); + expect(params.meshMessageDeliveriesWindow).toEqual(12 * 1000); expect(params.meshFailurePenaltyWeight).closeTo(-0.7474, TOLERANCE); expect(params.meshFailurePenaltyDecay).closeTo(0.93057, TOLERANCE); @@ -139,8 +139,8 @@ describe("computeGossipPeerScoreParams", function () { expect(params.meshMessageDeliveriesWeight).closeTo(-0.7474, TOLERANCE); expect(params.meshMessageDeliveriesThreshold).closeTo(17.15638, TOLERANCE); } else { - expect(params.meshMessageDeliveriesWeight).to.be.equal(0.0); - expect(params.meshMessageDeliveriesThreshold).to.be.equal(0.0); + expect(params.meshMessageDeliveriesWeight).toEqual(0.0); + expect(params.meshMessageDeliveriesThreshold).toEqual(0.0); } } @@ -151,10 +151,10 @@ describe("computeGossipPeerScoreParams", function () { }); const params = topics[topicString]; - expect(params.topicWeight).to.be.equal(0.5); + expect(params.topicWeight).toEqual(0.5); expect(params.timeInMeshWeight).closeTo(0.03333, TOLERANCE); - expect(params.timeInMeshQuantum).to.be.equal(12 * 1000); - expect(params.timeInMeshCap).to.be.equal(300.0); + expect(params.timeInMeshQuantum).toEqual(12 * 1000); + expect(params.timeInMeshCap).toEqual(300.0); expect(params.firstMessageDeliveriesWeight).closeTo(1.14716, TOLERANCE); expect(params.firstMessageDeliveriesDecay).closeTo(0.99283, TOLERANCE); expect(params.firstMessageDeliveriesCap).closeTo(34.8687, TOLERANCE); @@ -164,8 +164,8 @@ describe("computeGossipPeerScoreParams", function () { // Check message rate penalty params expect(params.meshMessageDeliveriesDecay).closeTo(0.97163, TOLERANCE); expect(params.meshMessageDeliveriesCap).closeTo(2.0547574, TOLERANCE); - expect(params.meshMessageDeliveriesActivation).to.be.equal(384 * 1000); - expect(params.meshMessageDeliveriesWindow).to.be.equal(12 * 1000); + expect(params.meshMessageDeliveriesActivation).toEqual(384 * 1000); + expect(params.meshMessageDeliveriesWindow).toEqual(12 * 1000); expect(params.meshFailurePenaltyWeight).closeTo(-468.9689, TOLERANCE); expect(params.meshFailurePenaltyDecay).closeTo(0.97163, TOLERANCE); @@ -173,8 +173,8 @@ describe("computeGossipPeerScoreParams", function () { expect(params.meshMessageDeliveriesWeight).closeTo(-468.9689, TOLERANCE); expect(params.meshMessageDeliveriesThreshold).closeTo(0.68491, TOLERANCE); } else { - expect(params.meshMessageDeliveriesWeight).to.be.equal(0.0); - expect(params.meshMessageDeliveriesThreshold).to.be.equal(0.0); + expect(params.meshMessageDeliveriesWeight).toEqual(0.0); + expect(params.meshMessageDeliveriesThreshold).toEqual(0.0); } } @@ -193,10 +193,10 @@ describe("computeGossipPeerScoreParams", function () { } function validateAllAttestationSubnetTopicScoreParams(params: TopicScoreParams, penaltiesActive: boolean): void { - expect(params.topicWeight).to.be.equal(0.015625); + expect(params.topicWeight).toEqual(0.015625); expect(params.timeInMeshWeight).closeTo(0.03333, TOLERANCE); - expect(params.timeInMeshQuantum).to.be.equal(12 * 1000); - expect(params.timeInMeshCap).to.be.equal(300.0); + expect(params.timeInMeshQuantum).toEqual(12 * 1000); + expect(params.timeInMeshCap).toEqual(300.0); expect(params.firstMessageDeliveriesWeight).closeTo(2.6807, TOLERANCE); expect(params.firstMessageDeliveriesDecay).closeTo(0.86596, TOLERANCE); expect(params.firstMessageDeliveriesCap).closeTo(14.9214, TOLERANCE); @@ -206,8 +206,8 @@ describe("computeGossipPeerScoreParams", function () { // Check message rate penalty params expect(params.meshMessageDeliveriesDecay).closeTo(0.96466, TOLERANCE); expect(params.meshMessageDeliveriesCap).closeTo(69.88248, TOLERANCE); - expect(params.meshMessageDeliveriesActivation).to.be.equal(204 * 1000); - expect(params.meshMessageDeliveriesWindow).to.be.equal(12 * 1000); + expect(params.meshMessageDeliveriesActivation).toEqual(204 * 1000); + expect(params.meshMessageDeliveriesWindow).toEqual(12 * 1000); expect(params.meshFailurePenaltyWeight).closeTo(-369.0421, TOLERANCE); expect(params.meshFailurePenaltyDecay).closeTo(0.96466, TOLERANCE); @@ -215,19 +215,19 @@ describe("computeGossipPeerScoreParams", function () { expect(params.meshMessageDeliveriesWeight).closeTo(-369.0421, TOLERANCE); expect(params.meshMessageDeliveriesThreshold).closeTo(4.367655, TOLERANCE); } else { - expect(params.meshMessageDeliveriesWeight).to.be.equal(0.0); - expect(params.meshMessageDeliveriesThreshold).to.be.equal(0.0); + expect(params.meshMessageDeliveriesWeight).toEqual(0.0); + expect(params.meshMessageDeliveriesThreshold).toEqual(0.0); } } }); function assertMessageRatePenaltiesDisabled(params: TopicScoreParams): void { - expect(params.meshMessageDeliveriesWeight).to.be.equal(0.0); - expect(params.meshMessageDeliveriesDecay).to.be.equal(0.0); - expect(params.meshMessageDeliveriesThreshold).to.be.equal(0.0); - expect(params.meshMessageDeliveriesCap).to.be.equal(0.0); - expect(params.meshFailurePenaltyWeight).to.be.equal(0.0); - expect(params.meshFailurePenaltyDecay).to.be.equal(0.0); - expect(params.meshMessageDeliveriesActivation).to.be.equal(0); - expect(params.meshMessageDeliveriesWindow).to.be.equal(0); + expect(params.meshMessageDeliveriesWeight).toEqual(0.0); + expect(params.meshMessageDeliveriesDecay).toEqual(0.0); + expect(params.meshMessageDeliveriesThreshold).toEqual(0.0); + expect(params.meshMessageDeliveriesCap).toEqual(0.0); + expect(params.meshFailurePenaltyWeight).toEqual(0.0); + expect(params.meshFailurePenaltyDecay).toEqual(0.0); + expect(params.meshMessageDeliveriesActivation).toEqual(0); + expect(params.meshMessageDeliveriesWindow).toEqual(0); } diff --git a/packages/beacon-node/test/unit-mainnet/network/subnets/util.test.ts b/packages/beacon-node/test/unit-mainnet/network/subnets/util.test.ts index b99d2417dd9d..af12ad3d80e8 100644 --- a/packages/beacon-node/test/unit-mainnet/network/subnets/util.test.ts +++ b/packages/beacon-node/test/unit-mainnet/network/subnets/util.test.ts @@ -1,4 +1,4 @@ -import {expect} from "chai"; +import {describe, it, expect} from "vitest"; import {bigIntToBytes} from "@lodestar/utils"; import {computeSubscribedSubnet} from "../../../../src/network/subnets/util.js"; @@ -61,7 +61,7 @@ describe("computeSubscribedSubnet", () => { for (const [index, {nodeId, epoch, expected}] of testCases.entries()) { it(`test case ${index}`, () => { // node is is of type uint256 = 32 bytes - expect(computeSubscribedSubnet(bigIntToBytes(BigInt(nodeId), 32, "be"), epoch)).to.deep.equal(expected); + expect(computeSubscribedSubnet(bigIntToBytes(BigInt(nodeId), 32, "be"), epoch)).toEqual(expected); }); } }); diff --git a/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts index 29df90e8548d..28c8fe652e8a 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts @@ -1,35 +1,23 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import {describe, it, expect, beforeAll} from "vitest"; -import {config} from "@lodestar/config/default"; +import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js"; import {getBeaconApi} from "../../../../../src/api/impl/beacon/index.js"; -import {setupApiImplTestServer, ApiImplTestModules} from "../../../../__mocks__/apiMocks.js"; -import {testLogger} from "../../../../utils/logger.js"; -import {MockedBeaconDb} from "../../../../__mocks__/mockedBeaconDb.js"; +import {Mutable} from "../../../../utils/types.js"; describe("beacon api implementation", function () { - const logger = testLogger(); - let dbStub: MockedBeaconDb; - let server: ApiImplTestModules; + let modules: ApiTestModules; + let api: ReturnType; beforeAll(function () { - server = setupApiImplTestServer(); - dbStub = new MockedBeaconDb(); + modules = getApiTestModules(); + api = getBeaconApi(modules); }); describe("getGenesis", function () { it("success", async function () { - const api = getBeaconApi({ - config, - chain: server.chainStub, - db: dbStub, - logger, - network: server.networkStub, - metrics: null, - }); - - /** eslint-disable @typescript-eslint/no-unsafe-member-access */ - (server.chainStub as any).genesisTime = 0; - (server.chainStub as any).genesisValidatorsRoot = Buffer.alloc(32); + (modules.chain as Mutable).genesisTime = 0; + (modules.chain as Mutable).genesisValidatorsRoot = + Buffer.alloc(32); const {data: genesis} = await api.getGenesis(); if (genesis === null || genesis === undefined) throw Error("Genesis is nullish"); expect(genesis.genesisForkVersion).toBeDefined(); diff --git a/packages/beacon-node/test/unit/api/impl/beacon/blocks/getBlockHeaders.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/blocks/getBlockHeaders.test.ts index 14853a8de9c4..d3d09f2a1fd6 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/blocks/getBlockHeaders.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/blocks/getBlockHeaders.test.ts @@ -2,19 +2,21 @@ import {toHexString} from "@chainsafe/ssz"; import {describe, it, expect, beforeEach, vi, afterEach} from "vitest"; import {when} from "vitest-when"; import {ssz} from "@lodestar/types"; +import {ApiTestModules, getApiTestModules} from "../../../../../utils/api.js"; import {generateProtoBlock, generateSignedBlockAtSlot} from "../../../../../utils/typeGenerator.js"; -import {setupApiImplTestServer, ApiImplTestModules} from "../../../../../__mocks__/apiMocks.js"; +import {getBeaconBlockApi} from "../../../../../../src/api/impl/beacon/blocks/index.js"; describe("api - beacon - getBlockHeaders", function () { - let server: ApiImplTestModules; + let modules: ApiTestModules; + let api: ReturnType; const parentRoot = toHexString(Buffer.alloc(32, 1)); beforeEach(function () { - server = setupApiImplTestServer(); - server.chainStub.forkChoice = server.forkChoiceStub; + modules = getApiTestModules(); + api = getBeaconBlockApi(modules); - vi.spyOn(server.dbStub.block, "get"); - vi.spyOn(server.dbStub.blockArchive, "getByParentRoot"); + vi.spyOn(modules.db.block, "get"); + vi.spyOn(modules.db.blockArchive, "getByParentRoot"); }); afterEach(() => { @@ -22,11 +24,11 @@ describe("api - beacon - getBlockHeaders", function () { }); it.skip("no filters - assume head slot", async function () { - server.forkChoiceStub.getHead.mockReturnValue(generateProtoBlock({slot: 1})); - when(server.chainStub.getCanonicalBlockAtSlot) + modules.forkChoice.getHead.mockReturnValue(generateProtoBlock({slot: 1})); + when(modules.chain.getCanonicalBlockAtSlot) .calledWith(1) .thenResolve({block: ssz.phase0.SignedBeaconBlock.defaultValue(), executionOptimistic: false}); - when(server.forkChoiceStub.getBlockSummariesAtSlot) + when(modules.forkChoice.getBlockSummariesAtSlot) .calledWith(1) .thenReturn([ generateProtoBlock(), @@ -39,92 +41,92 @@ describe("api - beacon - getBlockHeaders", function () { const blockFromDb3 = ssz.phase0.SignedBeaconBlock.defaultValue(); blockFromDb3.message.slot = 3; - server.dbStub.block.get.mockResolvedValue(blockFromDb3); + modules.db.block.get.mockResolvedValue(blockFromDb3); - server.dbStub.blockArchive.get.mockResolvedValue(null); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({}); + modules.db.blockArchive.get.mockResolvedValue(null); + const {data: blockHeaders} = await api.getBlockHeaders({}); expect(blockHeaders).not.toBeNull(); expect(blockHeaders.length).toBe(2); expect(blockHeaders.filter((header) => header.canonical).length).toBe(1); - expect(server.forkChoiceStub.getHead).toHaveBeenCalledTimes(1); - expect(server.chainStub.getCanonicalBlockAtSlot).toHaveBeenCalledTimes(1); - expect(server.forkChoiceStub.getBlockSummariesAtSlot).toHaveBeenCalledTimes(1); - expect(server.dbStub.block.get).toHaveBeenCalledTimes(1); + expect(modules.forkChoice.getHead).toHaveBeenCalledTimes(1); + expect(modules.chain.getCanonicalBlockAtSlot).toHaveBeenCalledTimes(1); + expect(modules.forkChoice.getBlockSummariesAtSlot).toHaveBeenCalledTimes(1); + expect(modules.db.block.get).toHaveBeenCalledTimes(1); }); it("future slot", async function () { - server.forkChoiceStub.getHead.mockReturnValue(generateProtoBlock({slot: 1})); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({slot: 2}); + modules.forkChoice.getHead.mockReturnValue(generateProtoBlock({slot: 1})); + const {data: blockHeaders} = await api.getBlockHeaders({slot: 2}); expect(blockHeaders.length).toBe(0); }); it("finalized slot", async function () { - server.forkChoiceStub.getHead.mockReturnValue(generateProtoBlock({slot: 2})); - when(server.chainStub.getCanonicalBlockAtSlot) + modules.forkChoice.getHead.mockReturnValue(generateProtoBlock({slot: 2})); + when(modules.chain.getCanonicalBlockAtSlot) .calledWith(0) .thenResolve({block: ssz.phase0.SignedBeaconBlock.defaultValue(), executionOptimistic: false}); - when(server.forkChoiceStub.getBlockSummariesAtSlot).calledWith(0).thenReturn([]); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({slot: 0}); + when(modules.forkChoice.getBlockSummariesAtSlot).calledWith(0).thenReturn([]); + const {data: blockHeaders} = await api.getBlockHeaders({slot: 0}); expect(blockHeaders.length).toBe(1); expect(blockHeaders[0].canonical).toBe(true); }); it("skip slot", async function () { - server.forkChoiceStub.getHead.mockReturnValue(generateProtoBlock({slot: 2})); - when(server.chainStub.getCanonicalBlockAtSlot).calledWith(0).thenResolve(null); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({slot: 0}); + modules.forkChoice.getHead.mockReturnValue(generateProtoBlock({slot: 2})); + when(modules.chain.getCanonicalBlockAtSlot).calledWith(0).thenResolve(null); + const {data: blockHeaders} = await api.getBlockHeaders({slot: 0}); expect(blockHeaders.length).toBe(0); }); it.skip("parent root filter - both finalized and non finalized results", async function () { - server.dbStub.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); - server.forkChoiceStub.getBlockSummariesByParentRoot.mockReturnValue([ + modules.db.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); + modules.forkChoice.getBlockSummariesByParentRoot.mockReturnValue([ generateProtoBlock({slot: 2}), generateProtoBlock({slot: 1}), ]); const canonical = generateSignedBlockAtSlot(2); - when(server.forkChoiceStub.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); - when(server.forkChoiceStub.getCanonicalBlockAtSlot) + when(modules.forkChoice.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); + when(modules.forkChoice.getCanonicalBlockAtSlot) .calledWith(2) .thenReturn(generateProtoBlock({blockRoot: toHexString(ssz.phase0.BeaconBlock.hashTreeRoot(canonical.message))})); - server.dbStub.block.get.mockResolvedValue(generateSignedBlockAtSlot(1)); - server.dbStub.block.get.mockResolvedValue(generateSignedBlockAtSlot(2)); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({parentRoot}); + modules.db.block.get.mockResolvedValue(generateSignedBlockAtSlot(1)); + modules.db.block.get.mockResolvedValue(generateSignedBlockAtSlot(2)); + const {data: blockHeaders} = await api.getBlockHeaders({parentRoot}); expect(blockHeaders.length).toBe(3); expect(blockHeaders.filter((b) => b.canonical).length).toBe(2); }); it("parent root - no finalized block", async function () { - server.dbStub.blockArchive.getByParentRoot.mockResolvedValue(null); - server.forkChoiceStub.getBlockSummariesByParentRoot.mockReturnValue([generateProtoBlock({slot: 1})]); - when(server.forkChoiceStub.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); - server.dbStub.block.get.mockResolvedValue(generateSignedBlockAtSlot(1)); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({parentRoot}); + modules.db.blockArchive.getByParentRoot.mockResolvedValue(null); + modules.forkChoice.getBlockSummariesByParentRoot.mockReturnValue([generateProtoBlock({slot: 1})]); + when(modules.forkChoice.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); + modules.db.block.get.mockResolvedValue(generateSignedBlockAtSlot(1)); + const {data: blockHeaders} = await api.getBlockHeaders({parentRoot}); expect(blockHeaders.length).toBe(1); }); it("parent root - no non finalized blocks", async function () { - server.dbStub.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); - server.forkChoiceStub.getBlockSummariesByParentRoot.mockReturnValue([]); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({parentRoot}); + modules.db.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); + modules.forkChoice.getBlockSummariesByParentRoot.mockReturnValue([]); + const {data: blockHeaders} = await api.getBlockHeaders({parentRoot}); expect(blockHeaders.length).toBe(1); }); it("parent root + slot filter", async function () { - server.dbStub.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); - server.forkChoiceStub.getBlockSummariesByParentRoot.mockReturnValue([ + modules.db.blockArchive.getByParentRoot.mockResolvedValue(ssz.phase0.SignedBeaconBlock.defaultValue()); + modules.forkChoice.getBlockSummariesByParentRoot.mockReturnValue([ generateProtoBlock({slot: 2}), generateProtoBlock({slot: 1}), ]); const canonical = generateSignedBlockAtSlot(2); - when(server.forkChoiceStub.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); - when(server.forkChoiceStub.getCanonicalBlockAtSlot) + when(modules.forkChoice.getCanonicalBlockAtSlot).calledWith(1).thenReturn(generateProtoBlock()); + when(modules.forkChoice.getCanonicalBlockAtSlot) .calledWith(2) .thenReturn(generateProtoBlock({blockRoot: toHexString(ssz.phase0.BeaconBlock.hashTreeRoot(canonical.message))})); - server.dbStub.block.get.mockResolvedValueOnce(generateSignedBlockAtSlot(1)); - server.dbStub.block.get.mockResolvedValueOnce(generateSignedBlockAtSlot(2)); - const {data: blockHeaders} = await server.blockApi.getBlockHeaders({ + modules.db.block.get.mockResolvedValueOnce(generateSignedBlockAtSlot(1)); + modules.db.block.get.mockResolvedValueOnce(generateSignedBlockAtSlot(2)); + const {data: blockHeaders} = await api.getBlockHeaders({ parentRoot: toHexString(Buffer.alloc(32, 1)), slot: 1, }); diff --git a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts index 5b09df7195b2..6986df406bf0 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts @@ -102,7 +102,7 @@ describe("beacon state api utils", function () { }); }); - describe("getStateValidatorIndex", async function () { + describe("getStateValidatorIndex", () => { const state = generateCachedAltairState(); const pubkey2index = state.epochCtx.pubkey2index; diff --git a/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts b/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts index d68f610d5c1f..27daaadae1fe 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts @@ -1,57 +1,29 @@ import {describe, it, expect, beforeEach, vi} from "vitest"; import {config} from "@lodestar/config/default"; -import {ssz} from "@lodestar/types"; import {MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH} from "@lodestar/params"; +import {ApiTestModules, getApiTestModules} from "../../../../../utils/api.js"; import {FAR_FUTURE_EPOCH} from "../../../../../../src/constants/index.js"; import {getValidatorApi} from "../../../../../../src/api/impl/validator/index.js"; -import {ApiModules} from "../../../../../../src/api/impl/types.js"; -import {generateState} from "../../../../../utils/state.js"; +import {generateState, zeroProtoBlock} from "../../../../../utils/state.js"; import {generateValidators} from "../../../../../utils/validator.js"; -import {setupApiImplTestServer, ApiImplTestModules} from "../../../../../__mocks__/apiMocks.js"; -import {testLogger} from "../../../../../utils/logger.js"; import {createCachedBeaconStateTest} from "../../../../../utils/cachedBeaconState.js"; -import {zeroProtoBlock} from "../../../../../utils/mocks/chain.js"; -import {MockedBeaconChain} from "../../../../../__mocks__/mockedBeaconChain.js"; -import {MockedBeaconDb} from "../../../../../__mocks__/mockedBeaconDb.js"; -import {MockedBeaconSync} from "../../../../../__mocks__/beaconSyncMock.js"; describe.skip("get proposers api impl", function () { - const logger = testLogger(); - - let chainStub: MockedBeaconChain, syncStub: MockedBeaconSync, dbStub: MockedBeaconDb; - let api: ReturnType; - let server: ApiImplTestModules; - let modules: ApiModules; + let modules: ApiTestModules; beforeEach(function () { - server = setupApiImplTestServer(); - chainStub = server.chainStub; - syncStub = server.syncStub; - chainStub.getCanonicalBlockAtSlot.mockResolvedValue({ - block: ssz.phase0.SignedBeaconBlock.defaultValue(), - executionOptimistic: false, - }); - dbStub = server.dbStub; - modules = { - chain: server.chainStub, - config, - db: server.dbStub, - logger, - network: server.networkStub, - sync: syncStub, - metrics: null, - }; + modules = getApiTestModules(); api = getValidatorApi(modules); - chainStub.forkChoice.getHead.mockReturnValue(zeroProtoBlock); + modules.forkChoice.getHead.mockReturnValue(zeroProtoBlock); }); it("should get proposers for next epoch", async function () { - syncStub.isSynced.mockReturnValue(true); - vi.spyOn(chainStub.clock, "currentEpoch", "get").mockReturnValue(0); - vi.spyOn(chainStub.clock, "currentSlot", "get").mockReturnValue(0); - dbStub.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); + modules.sync.isSynced.mockReturnValue(true); + vi.spyOn(modules.chain.clock, "currentEpoch", "get").mockReturnValue(0); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(0); + modules.db.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); const state = generateState( { slot: 0, @@ -66,23 +38,23 @@ describe.skip("get proposers api impl", function () { ); const cachedState = createCachedBeaconStateTest(state, config); - chainStub.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); + modules.chain.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); const stubGetNextBeaconProposer = vi.spyOn(cachedState.epochCtx, "getBeaconProposersNextEpoch"); const stubGetBeaconProposer = vi.spyOn(cachedState.epochCtx, "getBeaconProposer"); stubGetNextBeaconProposer.mockReturnValue([1]); const {data: result} = await api.getProposerDuties(1); expect(result.length).toBe(SLOTS_PER_EPOCH); // "stubGetBeaconProposer function should not have been called" - expect(stubGetNextBeaconProposer).toHaveBeenCalled(); + expect(stubGetNextBeaconProposer).toHaveBeenCalledWith(); // "stubGetBeaconProposer function should have been called" - expect(stubGetBeaconProposer).not.toHaveBeenCalled(); + expect(stubGetBeaconProposer).not.toHaveBeenCalledWith(); }); it("should have different proposer for current and next epoch", async function () { - syncStub.isSynced.mockReturnValue(true); - vi.spyOn(chainStub.clock, "currentEpoch", "get").mockReturnValue(0); - vi.spyOn(chainStub.clock, "currentSlot", "get").mockReturnValue(0); - dbStub.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); + modules.sync.isSynced.mockReturnValue(true); + vi.spyOn(modules.chain.clock, "currentEpoch", "get").mockReturnValue(0); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(0); + modules.db.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); const state = generateState( { slot: 0, @@ -96,7 +68,7 @@ describe.skip("get proposers api impl", function () { config ); const cachedState = createCachedBeaconStateTest(state, config); - chainStub.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); + modules.chain.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); const stubGetBeaconProposer = vi.spyOn(cachedState.epochCtx, "getBeaconProposer"); stubGetBeaconProposer.mockReturnValue(1); const {data: currentProposers} = await api.getProposerDuties(0); @@ -105,10 +77,10 @@ describe.skip("get proposers api impl", function () { }); it("should not get proposers for more than one epoch in the future", async function () { - syncStub.isSynced.mockReturnValue(true); - vi.spyOn(chainStub.clock, "currentEpoch", "get").mockReturnValue(0); - vi.spyOn(chainStub.clock, "currentSlot", "get").mockReturnValue(0); - dbStub.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); + modules.sync.isSynced.mockReturnValue(true); + vi.spyOn(modules.chain.clock, "currentEpoch", "get").mockReturnValue(0); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(0); + modules.db.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); const state = generateState( { slot: 0, @@ -122,9 +94,9 @@ describe.skip("get proposers api impl", function () { config ); const cachedState = createCachedBeaconStateTest(state, config); - chainStub.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); + modules.chain.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); const stubGetBeaconProposer = vi.spyOn(cachedState.epochCtx, "getBeaconProposer"); await expect(stubGetBeaconProposer).rejects.toThrow(); - await expect(api.getProposerDuties(2), "calling getProposerDuties should throw").rejects.toThrow(); + await expect(api.getProposerDuties(2)).rejects.toThrow(); }); }); diff --git a/packages/beacon-node/test/unit/api/impl/validator/produceAttestationData.test.ts b/packages/beacon-node/test/unit/api/impl/validator/produceAttestationData.test.ts index f177bccc359a..9c426c677974 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/produceAttestationData.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/produceAttestationData.test.ts @@ -1,52 +1,35 @@ import {describe, it, expect, beforeEach, vi} from "vitest"; -import {config} from "@lodestar/config/default"; import {ProtoBlock} from "@lodestar/fork-choice"; import {SyncState} from "../../../../../src/sync/interface.js"; -import {ApiModules} from "../../../../../src/api/impl/types.js"; +import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js"; import {getValidatorApi} from "../../../../../src/api/impl/validator/index.js"; -import {testLogger} from "../../../../utils/logger.js"; -import {ApiImplTestModules, setupApiImplTestServer} from "../../../../__mocks__/apiMocks.js"; describe("api - validator - produceAttestationData", function () { - const logger = testLogger(); - let syncStub: ApiImplTestModules["syncStub"]; - let modules: ApiModules; - let server: ApiImplTestModules; + let modules: ApiTestModules; + let api: ReturnType; beforeEach(function () { - server = setupApiImplTestServer(); - syncStub = server.syncStub; - modules = { - chain: server.chainStub, - config, - db: server.dbStub, - logger, - network: server.networkStub, - sync: syncStub, - metrics: null, - }; + modules = getApiTestModules(); + api = getValidatorApi(modules); }); it("Should throw when node is not synced", async function () { // Set the node's state to way back from current slot const currentSlot = 100000; const headSlot = 0; - vi.spyOn(server.chainStub.clock, "currentSlot", "get").mockReturnValue(currentSlot); - vi.spyOn(syncStub, "state", "get").mockReturnValue(SyncState.SyncingFinalized); - server.chainStub.forkChoice.getHead.mockReturnValue({slot: headSlot} as ProtoBlock); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(currentSlot); + vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.SyncingFinalized); + modules.forkChoice.getHead.mockReturnValue({slot: headSlot} as ProtoBlock); - // Should not allow any call to validator API - const api = getValidatorApi(modules); await expect(api.produceAttestationData(0, 0)).rejects.toThrow("Node is syncing"); }); it("Should throw error when node is stopped", async function () { const currentSlot = 100000; - vi.spyOn(server.chainStub.clock, "currentSlot", "get").mockReturnValue(currentSlot); - vi.spyOn(syncStub, "state", "get").mockReturnValue(SyncState.Stalled); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(currentSlot); + vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.Stalled); // Should not allow any call to validator API - const api = getValidatorApi(modules); await expect(api.produceAttestationData(0, 0)).rejects.toThrow("Node is syncing - waiting for peers"); }); }); diff --git a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV2.test.ts b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV2.test.ts index 56913e241e3b..deb148d34b5a 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV2.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV2.test.ts @@ -1,56 +1,29 @@ import {fromHexString} from "@chainsafe/ssz"; -import {describe, it, expect, beforeEach, afterEach, MockedObject, vi} from "vitest"; +import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; import {ssz} from "@lodestar/types"; -import {config} from "@lodestar/config/default"; import {ProtoBlock} from "@lodestar/fork-choice"; import {ForkName} from "@lodestar/params"; import {computeTimeAtSlot, CachedBeaconStateBellatrix} from "@lodestar/state-transition"; +import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js"; import {SyncState} from "../../../../../src/sync/interface.js"; -import {ApiModules} from "../../../../../src/api/impl/types.js"; import {getValidatorApi} from "../../../../../src/api/impl/validator/index.js"; -import {testLogger} from "../../../../utils/logger.js"; -import {ApiImplTestModules, setupApiImplTestServer} from "../../../../__mocks__/apiMocks.js"; import {BeaconChain} from "../../../../../src/chain/index.js"; import {generateCachedBellatrixState} from "../../../../utils/state.js"; -import {ExecutionEngineHttp} from "../../../../../src/execution/engine/http.js"; import {PayloadIdCache} from "../../../../../src/execution/engine/payloadIdCache.js"; import {toGraffitiBuffer} from "../../../../../src/util/graffiti.js"; import {BlockType, produceBlockBody} from "../../../../../src/chain/produceBlock/produceBlockBody.js"; import {generateProtoBlock} from "../../../../utils/typeGenerator.js"; import {ZERO_HASH_HEX} from "../../../../../src/constants/index.js"; -import {OpPool} from "../../../../../src/chain/opPools/opPool.js"; -import {AggregatedAttestationPool} from "../../../../../src/chain/opPools/index.js"; -import {Eth1ForBlockProduction} from "../../../../../src/eth1/index.js"; -import {BeaconProposerCache} from "../../../../../src/chain/beaconProposerCache.js"; describe("api/validator - produceBlockV2", function () { - const logger = testLogger(); - - let modules: ApiModules; - let server: ApiImplTestModules; - - let chainStub: ApiImplTestModules["chainStub"]; - let forkChoiceStub: ApiImplTestModules["forkChoiceStub"]; - let executionEngineStub: MockedObject; - let opPoolStub: MockedObject; - let aggregatedAttestationPoolStub: MockedObject; - let eth1Stub: MockedObject; - let syncStub: ApiImplTestModules["syncStub"]; + let api: ReturnType; + let modules: ApiTestModules; let state: CachedBeaconStateBellatrix; - let beaconProposerCacheStub: MockedObject; beforeEach(() => { - server = setupApiImplTestServer(); - chainStub = server.chainStub; - forkChoiceStub = server.chainStub.forkChoice; - executionEngineStub = server.chainStub.executionEngine; - opPoolStub = server.chainStub.opPool; - aggregatedAttestationPoolStub = server.chainStub.aggregatedAttestationPool; - eth1Stub = server.chainStub.eth1; - syncStub = server.syncStub; - beaconProposerCacheStub = server.chainStub.beaconProposerCache; - - // server.chainStub.logger = logger; + modules = getApiTestModules(); + api = getValidatorApi(modules); + state = generateCachedBellatrixState(); }); @@ -59,24 +32,13 @@ describe("api/validator - produceBlockV2", function () { }); it("correctly pass feeRecipient to produceBlock", async function () { - syncStub = server.syncStub; - modules = { - chain: server.chainStub, - config, - db: server.dbStub, - logger, - network: server.networkStub, - sync: syncStub, - metrics: null, - }; - const fullBlock = ssz.bellatrix.BeaconBlock.defaultValue(); const executionPayloadValue = ssz.Wei.defaultValue(); const consensusBlockValue = ssz.Wei.defaultValue(); const currentSlot = 100000; - vi.spyOn(server.chainStub.clock, "currentSlot", "get").mockReturnValue(currentSlot); - vi.spyOn(syncStub, "state", "get").mockReturnValue(SyncState.Synced); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(currentSlot); + vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.Synced); // Set the node's state to way back from current slot const slot = 100000; @@ -84,8 +46,7 @@ describe("api/validator - produceBlockV2", function () { const graffiti = "a".repeat(32); const feeRecipient = "0xcccccccccccccccccccccccccccccccccccccccc"; - const api = getValidatorApi(modules); - server.chainStub.produceBlock.mockResolvedValue({ + modules.chain.produceBlock.mockResolvedValue({ block: fullBlock, executionPayloadValue, consensusBlockValue, @@ -93,7 +54,7 @@ describe("api/validator - produceBlockV2", function () { // check if expectedFeeRecipient is passed to produceBlock await api.produceBlockV2(slot, randaoReveal, graffiti, {feeRecipient}); - expect(server.chainStub.produceBlock).toBeCalledWith({ + expect(modules.chain.produceBlock).toBeCalledWith({ randaoReveal, graffiti: toGraffitiBuffer(graffiti), slot, @@ -103,7 +64,7 @@ describe("api/validator - produceBlockV2", function () { // check that no feeRecipient is passed to produceBlock so that produceBlockBody will // pick it from beaconProposerCache await api.produceBlockV2(slot, randaoReveal, graffiti); - expect(server.chainStub.produceBlock).toBeCalledWith({ + expect(modules.chain.produceBlock).toBeCalledWith({ randaoReveal, graffiti: toGraffitiBuffer(graffiti), slot, @@ -120,23 +81,26 @@ describe("api/validator - produceBlockV2", function () { const feeRecipient = "0xccccccccccccccccccccccccccccccccccccccaa"; const headSlot = 0; - forkChoiceStub.getHead.mockReturnValue(generateProtoBlock({slot: headSlot})); + modules.forkChoice.getHead.mockReturnValue(generateProtoBlock({slot: headSlot})); - opPoolStub.getSlashingsAndExits.mockReturnValue([[], [], [], []]); - aggregatedAttestationPoolStub.getAttestationsForBlock.mockReturnValue([]); - eth1Stub.getEth1DataAndDeposits.mockResolvedValue({eth1Data: ssz.phase0.Eth1Data.defaultValue(), deposits: []}); - forkChoiceStub.getJustifiedBlock.mockReturnValue({} as ProtoBlock); - forkChoiceStub.getFinalizedBlock.mockReturnValue({} as ProtoBlock); - (executionEngineStub as unknown as {payloadIdCache: PayloadIdCache}).payloadIdCache = new PayloadIdCache(); + modules.chain["opPool"].getSlashingsAndExits.mockReturnValue([[], [], [], []]); + modules.chain["aggregatedAttestationPool"].getAttestationsForBlock.mockReturnValue([]); + modules.chain["eth1"].getEth1DataAndDeposits.mockResolvedValue({ + eth1Data: ssz.phase0.Eth1Data.defaultValue(), + deposits: [], + }); + modules.forkChoice.getJustifiedBlock.mockReturnValue({} as ProtoBlock); + modules.forkChoice.getFinalizedBlock.mockReturnValue({} as ProtoBlock); - executionEngineStub.notifyForkchoiceUpdate.mockResolvedValue("0x"); - executionEngineStub.getPayload.mockResolvedValue({ + modules.chain["executionEngine"].payloadIdCache = new PayloadIdCache(); + modules.chain["executionEngine"].notifyForkchoiceUpdate.mockResolvedValue("0x"); + modules.chain["executionEngine"].getPayload.mockResolvedValue({ executionPayload: ssz.bellatrix.ExecutionPayload.defaultValue(), executionPayloadValue, }); // use fee recipient passed in produceBlockBody call for payload gen in engine notifyForkchoiceUpdate - await produceBlockBody.call(chainStub as unknown as BeaconChain, BlockType.Full, state, { + await produceBlockBody.call(modules.chain as unknown as BeaconChain, BlockType.Full, state, { randaoReveal, graffiti: toGraffitiBuffer(graffiti), slot, @@ -147,21 +111,21 @@ describe("api/validator - produceBlockV2", function () { proposerPubKey: Uint8Array.from(Buffer.alloc(32, 1)), }); - expect(executionEngineStub.notifyForkchoiceUpdate).toBeCalledWith( + expect(modules.chain["executionEngine"].notifyForkchoiceUpdate).toBeCalledWith( ForkName.bellatrix, ZERO_HASH_HEX, ZERO_HASH_HEX, ZERO_HASH_HEX, { - timestamp: computeTimeAtSlot(chainStub.config, state.slot, state.genesisTime), + timestamp: computeTimeAtSlot(modules.config, state.slot, state.genesisTime), prevRandao: Uint8Array.from(Buffer.alloc(32, 0)), suggestedFeeRecipient: feeRecipient, } ); // use fee recipient set in beaconProposerCacheStub if none passed - beaconProposerCacheStub.getOrDefault.mockReturnValue("0x fee recipient address"); - await produceBlockBody.call(chainStub as unknown as BeaconChain, BlockType.Full, state, { + modules.chain["beaconProposerCache"].getOrDefault.mockReturnValue("0x fee recipient address"); + await produceBlockBody.call(modules.chain as unknown as BeaconChain, BlockType.Full, state, { randaoReveal, graffiti: toGraffitiBuffer(graffiti), slot, @@ -171,13 +135,13 @@ describe("api/validator - produceBlockV2", function () { proposerPubKey: Uint8Array.from(Buffer.alloc(32, 1)), }); - expect(executionEngineStub.notifyForkchoiceUpdate).toBeCalledWith( + expect(modules.chain["executionEngine"].notifyForkchoiceUpdate).toBeCalledWith( ForkName.bellatrix, ZERO_HASH_HEX, ZERO_HASH_HEX, ZERO_HASH_HEX, { - timestamp: computeTimeAtSlot(chainStub.config, state.slot, state.genesisTime), + timestamp: computeTimeAtSlot(modules.config, state.slot, state.genesisTime), prevRandao: Uint8Array.from(Buffer.alloc(32, 0)), suggestedFeeRecipient: "0x fee recipient address", } diff --git a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts index f1aa2cb791df..4484bcf03563 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts @@ -1,26 +1,17 @@ -import {describe, it, expect, beforeEach, afterEach, MockedObject, vi} from "vitest"; +import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; import {ssz} from "@lodestar/types"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {routes} from "@lodestar/api"; import {createBeaconConfig, createChainForkConfig, defaultChainConfig} from "@lodestar/config"; +import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js"; import {SyncState} from "../../../../../src/sync/interface.js"; -import {ApiModules} from "../../../../../src/api/impl/types.js"; import {getValidatorApi} from "../../../../../src/api/impl/validator/index.js"; -import {testLogger} from "../../../../utils/logger.js"; -import {ApiImplTestModules, setupApiImplTestServer} from "../../../../__mocks__/apiMocks.js"; -import {ExecutionBuilderHttp} from "../../../../../src/execution/builder/http.js"; import {CommonBlockBody} from "../../../../../src/chain/interface.js"; /* eslint-disable @typescript-eslint/naming-convention */ describe("api/validator - produceBlockV3", function () { - const logger = testLogger(); - - let modules: ApiModules; - let server: ApiImplTestModules; - - let chainStub: ApiImplTestModules["chainStub"]; - let executionBuilderStub: MockedObject; - let syncStub: ApiImplTestModules["syncStub"]; + let modules: ApiTestModules; + let api: ReturnType; const chainConfig = createChainForkConfig({ ...defaultChainConfig, @@ -31,13 +22,12 @@ describe("api/validator - produceBlockV3", function () { const config = createBeaconConfig(chainConfig, genesisValidatorsRoot); beforeEach(() => { - server = setupApiImplTestServer(); - chainStub = server.chainStub; - executionBuilderStub = server.chainStub.executionBuilder; - syncStub = server.syncStub; + modules = getApiTestModules(); + api = getValidatorApi({...modules, config}); - executionBuilderStub.status = true; + modules.chain.executionBuilder.status = true; }); + afterEach(() => { vi.clearAllMocks(); }); @@ -75,17 +65,6 @@ describe("api/validator - produceBlockV3", function () { finalSelection, ]) => { it(`produceBlockV3 - ${finalSelection} produces block`, async () => { - syncStub = server.syncStub; - modules = { - chain: server.chainStub, - config, - db: server.dbStub, - logger, - network: server.networkStub, - sync: syncStub, - metrics: null, - }; - const fullBlock = ssz.bellatrix.BeaconBlock.defaultValue(); const blindedBlock = ssz.bellatrix.BlindedBeaconBlock.defaultValue(); @@ -95,10 +74,8 @@ describe("api/validator - produceBlockV3", function () { const feeRecipient = "0xccccccccccccccccccccccccccccccccccccccaa"; const currentSlot = 1 * SLOTS_PER_EPOCH; - vi.spyOn(server.chainStub.clock, "currentSlot", "get").mockReturnValue(currentSlot); - vi.spyOn(syncStub, "state", "get").mockReturnValue(SyncState.Synced); - - const api = getValidatorApi(modules); + vi.spyOn(modules.chain.clock, "currentSlot", "get").mockReturnValue(currentSlot); + vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.Synced); if (enginePayloadValue !== null) { const commonBlockBody: CommonBlockBody = { @@ -114,26 +91,26 @@ describe("api/validator - produceBlockV3", function () { syncAggregate: fullBlock.body.syncAggregate, }; - chainStub.produceCommonBlockBody.mockResolvedValue(commonBlockBody); + modules.chain.produceCommonBlockBody.mockResolvedValue(commonBlockBody); - chainStub.produceBlock.mockResolvedValue({ + modules.chain.produceBlock.mockResolvedValue({ block: fullBlock, executionPayloadValue: BigInt(enginePayloadValue), consensusBlockValue: BigInt(consensusBlockValue), shouldOverrideBuilder, }); } else { - chainStub.produceBlock.mockRejectedValue(Error("not produced")); + modules.chain.produceBlock.mockRejectedValue(Error("not produced")); } if (builderPayloadValue !== null) { - chainStub.produceBlindedBlock.mockResolvedValue({ + modules.chain.produceBlindedBlock.mockResolvedValue({ block: blindedBlock, executionPayloadValue: BigInt(builderPayloadValue), consensusBlockValue: BigInt(consensusBlockValue), }); } else { - chainStub.produceBlindedBlock.mockRejectedValue(Error("not produced")); + modules.chain.produceBlindedBlock.mockRejectedValue(Error("not produced")); } const _skipRandaoVerification = false; const produceBlockOpts = { @@ -152,15 +129,15 @@ describe("api/validator - produceBlockV3", function () { // check call counts if (builderSelection === routes.validator.BuilderSelection.ExecutionOnly) { - expect(chainStub.produceBlindedBlock).toBeCalledTimes(0); + expect(modules.chain.produceBlindedBlock).toBeCalledTimes(0); } else { - expect(chainStub.produceBlindedBlock).toBeCalledTimes(1); + expect(modules.chain.produceBlindedBlock).toBeCalledTimes(1); } if (builderSelection === routes.validator.BuilderSelection.BuilderOnly) { - expect(chainStub.produceBlock).toBeCalledTimes(0); + expect(modules.chain.produceBlock).toBeCalledTimes(0); } else { - expect(chainStub.produceBlock).toBeCalledTimes(1); + expect(modules.chain.produceBlock).toBeCalledTimes(1); } }); } diff --git a/packages/beacon-node/test/unit/chain/archive/blockArchiver.test.ts b/packages/beacon-node/test/unit/chain/archive/blockArchiver.test.ts index 4abcd3e59ae8..d9c3b93a76ee 100644 --- a/packages/beacon-node/test/unit/chain/archive/blockArchiver.test.ts +++ b/packages/beacon-node/test/unit/chain/archive/blockArchiver.test.ts @@ -6,8 +6,8 @@ import {ZERO_HASH_HEX} from "../../../../src/constants/index.js"; import {generateProtoBlock} from "../../../utils/typeGenerator.js"; import {testLogger} from "../../../utils/logger.js"; import {archiveBlocks} from "../../../../src/chain/archiver/archiveBlocks.js"; -import {MockedBeaconDb, getMockedBeaconDb} from "../../../__mocks__/mockedBeaconDb.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; +import {MockedBeaconDb, getMockedBeaconDb} from "../../../mocks/mockedBeaconDb.js"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; describe("block archiver task", function () { const logger = testLogger(); diff --git a/packages/beacon-node/test/unit/chain/blocks/verifyBlocksSanityChecks.test.ts b/packages/beacon-node/test/unit/chain/blocks/verifyBlocksSanityChecks.test.ts index 1035d6e417fb..71ab5688a602 100644 --- a/packages/beacon-node/test/unit/chain/blocks/verifyBlocksSanityChecks.test.ts +++ b/packages/beacon-node/test/unit/chain/blocks/verifyBlocksSanityChecks.test.ts @@ -9,9 +9,9 @@ import {verifyBlocksSanityChecks as verifyBlocksImportSanityChecks} from "../../ import {BlockErrorCode} from "../../../../src/chain/errors/index.js"; import {expectThrowsLodestarError} from "../../../utils/errors.js"; import {IClock} from "../../../../src/util/clock.js"; -import {ClockStopped} from "../../../utils/mocks/clock.js"; +import {ClockStopped} from "../../../mocks/clock.js"; import {BlockSource, getBlockInput} from "../../../../src/chain/blocks/types.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; describe("chain / blocks / verifyBlocksSanityChecks", function () { let forkChoice: MockedBeaconChain["forkChoice"]; diff --git a/packages/beacon-node/test/unit/chain/bls/bls.test.ts b/packages/beacon-node/test/unit/chain/bls/bls.test.ts index 763ba71d379f..e5b844262632 100644 --- a/packages/beacon-node/test/unit/chain/bls/bls.test.ts +++ b/packages/beacon-node/test/unit/chain/bls/bls.test.ts @@ -46,7 +46,7 @@ describe("BlsVerifier ", function () { it("should return false if at least one signature is malformed", async () => { // signature is malformed const malformedSignature = Buffer.alloc(96, 10); - expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).to.throws(); + expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).toThrow(); sets[1].signature = malformedSignature; expect(await verifier.verifySignatureSets(sets)).toBe(false); }); @@ -79,7 +79,7 @@ describe("BlsVerifier ", function () { it("should return false for malformed signature", async () => { // signature is malformed const malformedSignature = Buffer.alloc(96, 10); - expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).to.throws(); + expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).toThrow(); sets[1].signature = malformedSignature; expect(await verifier.verifySignatureSetsSameMessage(sets, signingRoot)).toEqual([true, false, true]); }); diff --git a/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts b/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts index 76b2aab29abb..20b6fc8d7a00 100644 --- a/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts +++ b/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts @@ -1,5 +1,5 @@ import {toHexString} from "@chainsafe/ssz"; -import {describe, it, expect, beforeEach, beforeAll} from "vitest"; +import {describe, it, expect, beforeEach, beforeAll, vi} from "vitest"; import {config} from "@lodestar/config/default"; import {CheckpointWithHex, ExecutionStatus, ForkChoice} from "@lodestar/fork-choice"; import {FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE} from "@lodestar/params"; @@ -16,6 +16,9 @@ import {createCachedBeaconStateTest} from "../../../utils/cachedBeaconState.js"; import {generateState} from "../../../utils/state.js"; import {generateValidators} from "../../../utils/validator.js"; +// We mock this package globally +vi.unmock("@lodestar/fork-choice"); + describe("LodestarForkChoice", function () { let forkChoice: ForkChoice; const anchorState = createCachedBeaconStateTest( @@ -86,7 +89,6 @@ describe("LodestarForkChoice", function () { const parentBlockHex = ssz.phase0.BeaconBlock.hashTreeRoot(parentBlock.message); const orphanedBlockHex = ssz.phase0.BeaconBlock.hashTreeRoot(orphanedBlock.message); // forkchoice tie-break condition is based on root hex - // eslint-disable-next-line chai-expect/no-inner-compare expect(orphanedBlockHex > parentBlockHex).toBe(true); const currentSlot = childBlock.message.slot; forkChoice.updateTime(currentSlot); diff --git a/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts index b181aa1c1292..48abfbc35675 100644 --- a/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts @@ -5,6 +5,7 @@ import {describe, it, expect, beforeEach, beforeAll, afterEach, vi} from "vitest import {CachedBeaconStateAllForks} from "@lodestar/state-transition"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {ssz, phase0} from "@lodestar/types"; +import {MockedForkChoice, getMockedForkChoice} from "../../../mocks/mockedBeaconChain.js"; import { AggregatedAttestationPool, aggregateInto, @@ -17,7 +18,6 @@ import {generateCachedAltairState} from "../../../utils/state.js"; import {renderBitArray} from "../../../utils/render.js"; import {ZERO_HASH_HEX} from "../../../../src/constants/constants.js"; import {generateProtoBlock} from "../../../utils/typeGenerator.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; /** Valid signature of random data to prevent BLS errors */ const validSignature = fromHexString( @@ -38,12 +38,12 @@ describe("AggregatedAttestationPool", function () { const attDataRootHex = toHexString(ssz.phase0.AttestationData.hashTreeRoot(attestation.data)); const committee = [0, 1, 2, 3]; - let forkchoiceStub: MockedBeaconChain["forkChoice"]; + let forkchoiceStub: MockedForkChoice; beforeEach(() => { pool = new AggregatedAttestationPool(); altairState = originalState.clone(); - forkchoiceStub = getMockedBeaconChain().forkChoice; + forkchoiceStub = getMockedForkChoice(); }); afterEach(() => { diff --git a/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts b/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts index f4fa68609015..6d1be3fa8dd5 100644 --- a/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts +++ b/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts @@ -3,13 +3,12 @@ import {config} from "@lodestar/config/default"; import {ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; import {routes} from "@lodestar/api"; import {ProtoBlock} from "@lodestar/fork-choice"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../mocks/mockedBeaconChain.js"; +import {MockedLogger, getMockedLogger} from "../../mocks/loggerMock.js"; import {IChainOptions} from "../../../src/chain/options.js"; import {PrepareNextSlotScheduler} from "../../../src/chain/prepareNextSlot.js"; -import {generateCachedBellatrixState} from "../../utils/state.js"; +import {generateCachedBellatrixState, zeroProtoBlock} from "../../utils/state.js"; import {PayloadIdCache} from "../../../src/execution/engine/payloadIdCache.js"; -import {zeroProtoBlock} from "../../utils/mocks/chain.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../__mocks__/mockedBeaconChain.js"; -import {MockedLogger, getMockedLogger} from "../../__mocks__/loggerMock.js"; describe("PrepareNextSlot scheduler", () => { const abortController = new AbortController(); @@ -62,7 +61,7 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(2 * SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); expect(regenStub.getBlockSlotState).not.toHaveBeenCalled(); }); @@ -74,8 +73,8 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); - expect(regenStub.getBlockSlotState).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); + expect(regenStub.getBlockSlotState).toHaveBeenCalledOnce(); }); it("pre bellatrix - should handle regen.getBlockSlotState error", async () => { @@ -87,8 +86,8 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); - expect(regenStub.getBlockSlotState).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); + expect(regenStub.getBlockSlotState).toHaveBeenCalledOnce(); expect(loggerStub.error).toHaveBeenCalledTimes(1); }); @@ -99,7 +98,7 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(2 * SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledWith(); expect(regenStub.getBlockSlotState).not.toHaveBeenCalled(); }); @@ -112,8 +111,8 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); - expect(regenStub.getBlockSlotState).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); + expect(regenStub.getBlockSlotState).toHaveBeenCalledOnce(); }); it("bellatrix - should prepare payload", async () => { @@ -135,11 +134,11 @@ describe("PrepareNextSlot scheduler", () => { vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalled(); - expect(regenStub.getBlockSlotState).toHaveBeenCalled(); - expect(updateBuilderStatus).toHaveBeenCalled(); - expect(forkChoiceStub.getJustifiedBlock).toHaveBeenCalled(); - expect(forkChoiceStub.getFinalizedBlock).toHaveBeenCalled(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); + expect(regenStub.getBlockSlotState).toHaveBeenCalledOnce(); + expect(updateBuilderStatus).toHaveBeenCalledOnce(); + expect(forkChoiceStub.getJustifiedBlock).toHaveBeenCalledOnce(); + expect(forkChoiceStub.getFinalizedBlock).toHaveBeenCalledOnce(); expect(executionEngineStub.notifyForkchoiceUpdate).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledTimes(1); }); diff --git a/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts b/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts index c389e1b81e70..16af7b0df10e 100644 --- a/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts +++ b/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts @@ -114,16 +114,16 @@ describe("SeenGossipBlockInput", () => { if (expectedResponseType instanceof Error) { expect.fail(`expected to fail with error: ${expectedResponseType.message}`); } else if (expectedResponseType === null) { - expect(blockInputRes).toBeNull; + expect(blockInputRes).toBeNull(); } else { - expect(blockInputRes.blockInput?.type).to.be.equal(expectedResponseType); + expect(blockInputRes.blockInput?.type).toEqual(expectedResponseType); } } else { const index = parseInt(inputEvent.split("blob")[1] ?? "0"); const blobSidecar = blobSidecars[index]; - expect(blobSidecar).not.equal(undefined); + expect(blobSidecar).not.toBeUndefined(); - const blockInputRes = seenGossipBlockInput.getGossipBlockInput(config, { + const blobInputRes = seenGossipBlockInput.getGossipBlockInput(config, { type: GossipedInputType.blob, blobSidecar, blobBytes: null, @@ -132,16 +132,17 @@ describe("SeenGossipBlockInput", () => { if (expectedResponseType instanceof Error) { expect.fail(`expected to fail with error: ${expectedResponseType.message}`); } else if (expectedResponseType === null) { - expect(blockInputRes).toBeNull; + expect(blobInputRes.blockInput).toBeNull(); + expect(blobInputRes.blockInputMeta.expectedBlobs).toBeNull(); } else { - expect(blockInputRes.blockInput?.type).to.equal(expectedResponseType); + expect(blobInputRes.blockInput?.type).toEqual(expectedResponseType); } } } catch (e) { if (!(e as Error).message.includes("expected to fail with error")) { if (!(expectedResponseType instanceof Error)) { expect.fail( - `expected not to fail with respose=${expectedResponseType} but errored: ${(e as Error).message}` + `expected not to fail with response=${expectedResponseType} but errored: ${(e as Error).message}` ); } } diff --git a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts index 186739ff2475..6295a993c072 100644 --- a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts +++ b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts @@ -19,19 +19,19 @@ describe("ShufflingCache", function () { it("should get shuffling from cache", async function () { const decisionRoot = getShufflingDecisionBlock(state, currentEpoch); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).to.deep.equal(state.epochCtx.currentShuffling); + expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); }); it("should bound by maxSize(=1)", async function () { const decisionRoot = getShufflingDecisionBlock(state, currentEpoch); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).to.deep.equal(state.epochCtx.currentShuffling); + expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); // insert promises at the same epoch does not prune the cache shufflingCache.insertPromise(currentEpoch, "0x00"); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).to.deep.equal(state.epochCtx.currentShuffling); + expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); // insert shufflings at other epochs does prune the cache shufflingCache.processState(state, currentEpoch + 1); // the current shuffling is not available anymore - expect(await shufflingCache.get(currentEpoch, decisionRoot)).to.be.null; + expect(await shufflingCache.get(currentEpoch, decisionRoot)).toBeNull(); }); it("should return shuffling from promise", async function () { @@ -40,8 +40,8 @@ describe("ShufflingCache", function () { const shufflingRequest0 = shufflingCache.get(currentEpoch + 1, nextDecisionRoot); const shufflingRequest1 = shufflingCache.get(currentEpoch + 1, nextDecisionRoot); shufflingCache.processState(state, currentEpoch + 1); - expect(await shufflingRequest0).to.deep.equal(state.epochCtx.nextShuffling); - expect(await shufflingRequest1).to.deep.equal(state.epochCtx.nextShuffling); + expect(await shufflingRequest0).toEqual(state.epochCtx.nextShuffling); + expect(await shufflingRequest1).toEqual(state.epochCtx.nextShuffling); }); it("should support up to 2 promises at a time", async function () { @@ -49,6 +49,6 @@ describe("ShufflingCache", function () { shufflingCache.insertPromise(currentEpoch, "0x00"); shufflingCache.insertPromise(currentEpoch, "0x01"); // inserting other promise should throw error - expect(() => shufflingCache.insertPromise(currentEpoch, "0x02")).to.throw(); + expect(() => shufflingCache.insertPromise(currentEpoch, "0x02")).toThrow(); }); }); diff --git a/packages/beacon-node/test/unit/chain/stateCache/fifoBlockStateCache.test.ts b/packages/beacon-node/test/unit/chain/stateCache/fifoBlockStateCache.test.ts index 62f2bff13d19..4628b1b07220 100644 --- a/packages/beacon-node/test/unit/chain/stateCache/fifoBlockStateCache.test.ts +++ b/packages/beacon-node/test/unit/chain/stateCache/fifoBlockStateCache.test.ts @@ -91,15 +91,15 @@ describe("FIFOBlockStateCache", function () { it(name, () => { // move to head this state cache.setHeadState(headState); - expect(cache.size).to.be.equal(2, "Size must be same as initial 2"); + expect(cache.size).toEqualWithMessage(2, "Size must be same as initial 2"); for (const addAsHead of addAsHeadArr) { cache.add(state3, addAsHead); } - expect(cache.size).to.be.equal(2, "Size should reduce to initial 2 after prunning"); + expect(cache.size).toEqualWithMessage(2, "Size should reduce to initial 2 after prunning"); expect(cache.dumpKeyOrder()).toEqual(keptStates); expect(cache.get(prunedState)).toBeNull(); for (const key of keptStates) { - expect(cache.get(key), `must have key ${key}`).to.be.not.null; + expect(cache.get(key)).not.toBeNull(); } }); } diff --git a/packages/beacon-node/test/unit/chain/stateCache/persistentCheckpointsCache.test.ts b/packages/beacon-node/test/unit/chain/stateCache/persistentCheckpointsCache.test.ts index 18bdfac89793..9c37b863623d 100644 --- a/packages/beacon-node/test/unit/chain/stateCache/persistentCheckpointsCache.test.ts +++ b/packages/beacon-node/test/unit/chain/stateCache/persistentCheckpointsCache.test.ts @@ -99,15 +99,15 @@ describe("PersistentCheckpointStateCache", function () { // cp0 expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch)?.hashTreeRoot()).toEqual(states["cp0a"].hashTreeRoot()); expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch + 1)?.hashTreeRoot()).toEqual(states["cp0a"].hashTreeRoot()); - expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch - 1)?.hashTreeRoot()).to.be.undefined; + expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch - 1)?.hashTreeRoot()).toBeUndefined(); // cp1 expect(cache.getLatest(cp1Hex.rootHex, cp1.epoch)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); expect(cache.getLatest(cp1Hex.rootHex, cp1.epoch + 1)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); - expect(cache.getLatest(cp1Hex.rootHex, cp1.epoch - 1)?.hashTreeRoot()).to.be.undefined; + expect(cache.getLatest(cp1Hex.rootHex, cp1.epoch - 1)?.hashTreeRoot()).toBeUndefined(); // cp2 - expect(cache.getLatest(cp2Hex.rootHex, cp2.epoch)?.hashTreeRoot()).to.be.undefined; + expect(cache.getLatest(cp2Hex.rootHex, cp2.epoch)?.hashTreeRoot()).toBeUndefined(); }); it("getOrReloadLatest", async () => { @@ -119,15 +119,15 @@ describe("PersistentCheckpointStateCache", function () { expect(Array.from(fileApisBuffer.keys())).toEqual([persistent0bKey]); // getLatest() does not reload from disk - expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch)).to.be.null; - expect(cache.getLatest(cp0bHex.rootHex, cp0b.epoch)).to.be.null; + expect(cache.getLatest(cp0aHex.rootHex, cp0a.epoch)).toBeNull(); + expect(cache.getLatest(cp0bHex.rootHex, cp0b.epoch)).toBeNull(); // cp0a has the root from previous epoch so we only prune it from db - expect(await cache.getOrReloadLatest(cp0aHex.rootHex, cp0a.epoch)).to.be.null; + expect(await cache.getOrReloadLatest(cp0aHex.rootHex, cp0a.epoch)).toBeNull(); // but getOrReloadLatest() does for cp0b expect((await cache.getOrReloadLatest(cp0bHex.rootHex, cp0b.epoch))?.serialize()).toEqual(stateBytes["cp0b"]); expect((await cache.getOrReloadLatest(cp0bHex.rootHex, cp0b.epoch + 1))?.serialize()).toEqual(stateBytes["cp0b"]); - expect((await cache.getOrReloadLatest(cp0bHex.rootHex, cp0b.epoch - 1))?.serialize()).to.be.undefined; + expect((await cache.getOrReloadLatest(cp0bHex.rootHex, cp0b.epoch - 1))?.serialize()).toBeUndefined(); }); it("pruneFinalized and getStateOrBytes", async function () { @@ -139,15 +139,15 @@ describe("PersistentCheckpointStateCache", function () { expect(Array.from(fileApisBuffer.keys())).toEqual([persistent0bKey]); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // cp1 is in memory - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // cp2 is in memory - expect(cache.get(cp2Hex)).to.be.not.null; + expect(cache.get(cp2Hex)).not.toBeNull(); // finalize epoch cp2 cache.pruneFinalized(cp2.epoch); expect(fileApisBuffer.size).toEqual(0); - expect(cache.get(cp1Hex)).to.be.null; - expect(cache.get(cp2Hex)).to.be.not.null; - expect(await cache.getStateOrBytes(cp0bHex)).to.be.null; + expect(cache.get(cp1Hex)).toBeNull(); + expect(cache.get(cp2Hex)).not.toBeNull(); + expect(await cache.getStateOrBytes(cp0bHex)).toBeNull(); }); describe("findSeedStateToReload", () => { @@ -258,15 +258,15 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // epoch 22 has 1 checkpoint state - expect(cache.get(cp2Hex)).to.be.not.null; + expect(cache.get(cp2Hex)).not.toBeNull(); // epoch 21 has 1 checkpoint state - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0bHex)).toBeNull(); // but cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // while cp0aHex is not - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -300,15 +300,15 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // epoch 22 has 1 checkpoint state - expect(cache.get(cp2Hex)).to.be.not.null; + expect(cache.get(cp2Hex)).not.toBeNull(); // epoch 21 has 1 checkpoint state - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0bHex)).toBeNull(); // but cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // while cp0aHex is not - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -346,13 +346,13 @@ describe("PersistentCheckpointStateCache", function () { await cache.processState(toHexString(root3), blockStateRoot3); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // epoch 22 has 2 checkpoint states - expect(cache.get(cp2Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp2a))).to.be.not.null; + expect(cache.get(cp2Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp2a))).not.toBeNull(); // epoch 21 has 1 checkpoint state - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -399,13 +399,13 @@ describe("PersistentCheckpointStateCache", function () { await cache.processState(toHexString(root3), blockStateRoot3); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // epoch 21 and 22 have 2 checkpoint states - expect(cache.get(cp1Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1a))).to.be.not.null; - expect(cache.get(cp2Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp2a))).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1a))).not.toBeNull(); + expect(cache.get(cp2Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp2a))).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -424,7 +424,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(cp2.root), states["cp2"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // cp0a was pruned from memory and not in disc - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); // regen needs to regen cp0a cache.add(cp0a, states["cp0a"]); @@ -455,13 +455,13 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(root3), blockStateRoot3)).toEqual(1); await assertPersistedCheckpointState([cp0b, cp0a], [stateBytes["cp0b"], stateBytes["cp0a"]]); // epoch 21 and 22 have 2 checkpoint states - expect(cache.get(cp1Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1a))).to.be.not.null; - expect(cache.get(cp2Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp2a))).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1a))).not.toBeNull(); + expect(cache.get(cp2Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp2a))).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -480,7 +480,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(cp2.root), states["cp2"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // cp0a was pruned from memory and not in disc - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); // regen needs to reload cp0b cache.add(cp0b, states["cp0b"]); @@ -511,13 +511,13 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); // epoch 21 and 22 have 2 checkpoint states - expect(cache.get(cp1Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1b))).to.be.not.null; - expect(cache.get(cp2Hex)).to.be.not.null; - expect(cache.get(toCheckpointHex(cp2b))).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1b))).not.toBeNull(); + expect(cache.get(cp2Hex)).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp2b))).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); }); }); @@ -557,14 +557,14 @@ describe("PersistentCheckpointStateCache", function () { expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // epoch 21 has 1 checkpoint state - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); // but cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // while cp0aHex is not - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -597,14 +597,14 @@ describe("PersistentCheckpointStateCache", function () { await cache.processState(toHexString(root3), blockStateRoot3); // epoch 21 has 1 checkpoint state - expect(cache.get(cp1Hex)).to.be.not.null; + expect(cache.get(cp1Hex)).not.toBeNull(); // epoch 20 has 0 checkpoint state - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); // but cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // while cp0aHex is not - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -647,8 +647,8 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // keep these 2 cp states at epoch 21 - expect(cache.get(toCheckpointHex(cp1a))).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1))).to.be.not.null; + expect(cache.get(toCheckpointHex(cp1a))).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1))).not.toBeNull(); }); // epoch: 19 20 21 22 23 @@ -685,8 +685,8 @@ describe("PersistentCheckpointStateCache", function () { // but cp0b in-memory state is pruned expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // keep these 2 cp states at epoch 21 - expect(cache.get(toCheckpointHex(cp1b))).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1))).to.be.not.null; + expect(cache.get(toCheckpointHex(cp1b))).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1))).not.toBeNull(); }); // epoch: 19 20 21 22 23 @@ -708,8 +708,8 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(cp1.root), states["cp1"])).toEqual(0); expect(fileApisBuffer.size).toEqual(0); // at epoch 20, there should be 2 cps in memory - expect(cache.get(cp0aHex)).to.be.not.null; - expect(cache.get(cp0bHex)).to.be.not.null; + expect(cache.get(cp0aHex)).not.toBeNull(); + expect(cache.get(cp0bHex)).not.toBeNull(); await assertPersistedCheckpointState([], []); // cp1 @@ -720,11 +720,11 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // 2 checkpoint states at epoch 20 are pruned - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); // only cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); // root2, regen cp0a cache.add(cp0a, states["cp0a"]); @@ -740,8 +740,8 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b, cp0a], [stateBytes["cp0b"], stateBytes["cp0a"]]); expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // keep these 2 cp states at epoch 21 - expect(cache.get(toCheckpointHex(cp1a))).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1))).to.be.not.null; + expect(cache.get(toCheckpointHex(cp1a))).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1))).not.toBeNull(); }); // epoch: 19 20 21 22 23 @@ -762,11 +762,11 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // 2 checkpoint states at epoch 20 are pruned - expect(cache.get(cp0aHex)).to.be.null; - expect(cache.get(cp0bHex)).to.be.null; + expect(cache.get(cp0aHex)).toBeNull(); + expect(cache.get(cp0bHex)).toBeNull(); // only cp0bHex is persisted expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); // root2, regen cp0a cache.add(cp0a, states["cp0a"]); @@ -782,8 +782,8 @@ describe("PersistentCheckpointStateCache", function () { await assertPersistedCheckpointState([cp0b, cp0a], [stateBytes["cp0b"], stateBytes["cp0a"]]); expect(cache.get(cp1Hex)?.hashTreeRoot()).toEqual(states["cp1"].hashTreeRoot()); // keep these 2 cp states at epoch 21 - expect(cache.get(toCheckpointHex(cp1a))).to.be.not.null; - expect(cache.get(toCheckpointHex(cp1))).to.be.not.null; + expect(cache.get(toCheckpointHex(cp1a))).not.toBeNull(); + expect(cache.get(toCheckpointHex(cp1))).not.toBeNull(); }); describe("processState, maxEpochsInMemory = 0", () => { @@ -808,7 +808,7 @@ describe("PersistentCheckpointStateCache", function () { it("no reorg", async () => { expect(await cache.processState(toHexString(root0b), states["cp0b"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); const root1a = Buffer.alloc(32, 100); @@ -818,7 +818,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(root1a), state1a)).toEqual(0); // nothing change - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); }); @@ -832,7 +832,7 @@ describe("PersistentCheckpointStateCache", function () { it("reorg in same epoch", async () => { expect(await cache.processState(toHexString(root0b), states["cp0b"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); const root1a = Buffer.alloc(32, 100); @@ -842,7 +842,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(root1a), state1a)).toEqual(0); // nothing change - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); // simulate reload cp1b @@ -856,7 +856,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(root1b), state1b)).toEqual(0); // although states["cp0b"] is pruned expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); }); // epoch: 19 20 21 22 23 @@ -869,7 +869,7 @@ describe("PersistentCheckpointStateCache", function () { it("reorg 1 epoch", async () => { expect(await cache.processState(toHexString(root0b), states["cp0b"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); const root1a = Buffer.alloc(32, 100); @@ -879,7 +879,7 @@ describe("PersistentCheckpointStateCache", function () { expect(await cache.processState(toHexString(root1a), state1a)).toEqual(0); // nothing change - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); const root1b = Buffer.alloc(32, 101); @@ -908,7 +908,7 @@ describe("PersistentCheckpointStateCache", function () { it("reorg 2 epochs", async () => { expect(await cache.processState(toHexString(root0b), states["cp0b"])).toEqual(1); await assertPersistedCheckpointState([cp0b], [stateBytes["cp0b"]]); - expect(await cache.getStateOrBytes(cp0aHex)).to.be.null; + expect(await cache.getStateOrBytes(cp0aHex)).toBeNull(); expect(await cache.getStateOrBytes(cp0bHex)).toEqual(stateBytes["cp0b"]); cache.add(cp1, states["cp1"]); @@ -948,7 +948,7 @@ describe("PersistentCheckpointStateCache", function () { const cpHex = toCheckpointHex(cp); expect(await cache.getStateOrBytes(cpHex)).toStrictEqual(stateBytesArr[i]); // simple get() does not reload from disk - expect(cache.get(cpHex)).to.be.null; + expect(cache.get(cpHex)).toBeNull(); } } }); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation.test.ts deleted file mode 100644 index efd7d3c00cbb..000000000000 --- a/packages/beacon-node/test/unit/chain/validation/attestation.test.ts +++ /dev/null @@ -1,591 +0,0 @@ -import {BitArray} from "@chainsafe/ssz"; -import type {PublicKey, SecretKey} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; -import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; -import {ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; -import {EpochDifference, ProtoBlock} from "@lodestar/fork-choice"; -import {EpochShuffling, SignatureSetType, computeStartSlotAtEpoch} from "@lodestar/state-transition"; -import {ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages -import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../state-transition/test/perf/util.js"; -import {IBeaconChain} from "../../../../src/chain/index.js"; -import { - AttestationError, - AttestationErrorCode, - GossipAction, - GossipErrorCode, -} from "../../../../src/chain/errors/index.js"; -import { - ApiAttestation, - GossipAttestation, - validateApiAttestation, - Step0Result, - validateAttestation, - validateGossipAttestationsSameAttData, - getShufflingForAttestationVerification, -} from "../../../../src/chain/validation/index.js"; -import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; -import {memoOnce} from "../../../utils/cache.js"; -import {getAttestationValidData, AttestationValidDataOpts} from "../../../utils/validationData/attestation.js"; -import {RegenCaller} from "../../../../src/chain/regen/interface.js"; -import {ZERO_HASH_HEX} from "../../../../src/constants/constants.js"; - -import {BlsSingleThreadVerifier} from "../../../../src/chain/bls/singleThread.js"; -import {SeenAttesters} from "../../../../src/chain/seenCache/seenAttesters.js"; -import {getAttDataBase64FromAttestationSerialized} from "../../../../src/util/sszBytes.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; - -describe("validateGossipAttestationsSameAttData", () => { - // phase0Result specifies whether the attestation is valid in phase0 - // phase1Result specifies signature verification - const testCases: {phase0Result: boolean[]; phase1Result: boolean[]; seenAttesters: number[]}[] = [ - { - phase0Result: [true, true, true, true, true], - phase1Result: [true, true, true, true, true], - seenAttesters: [0, 1, 2, 3, 4], - }, - { - phase0Result: [false, true, true, true, true], - phase1Result: [true, false, true, true, true], - seenAttesters: [2, 3, 4], - }, - { - phase0Result: [false, false, true, true, true], - phase1Result: [true, false, false, true, true], - seenAttesters: [3, 4], - }, - { - phase0Result: [false, false, true, true, true], - phase1Result: [true, false, false, true, false], - seenAttesters: [3], - }, - { - phase0Result: [false, false, true, true, true], - phase1Result: [true, true, false, false, false], - seenAttesters: [], - }, - ]; - - type Keypair = {publicKey: PublicKey; secretKey: SecretKey}; - const keypairs = new Map(); - function getKeypair(i: number): Keypair { - let keypair = keypairs.get(i); - if (!keypair) { - const bytes = new Uint8Array(32); - const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); - dataView.setUint32(0, i + 1, true); - const secretKey = bls.SecretKey.fromBytes(bytes); - const publicKey = secretKey.toPublicKey(); - keypair = {secretKey, publicKey}; - keypairs.set(i, keypair); - } - return keypair; - } - - let chain: IBeaconChain; - const signingRoot = Buffer.alloc(32, 1); - - beforeEach(() => { - chain = { - bls: new BlsSingleThreadVerifier({metrics: null}), - seenAttesters: new SeenAttesters(), - opts: { - minSameMessageSignatureSetsToBatch: 2, - } as IBeaconChain["opts"], - } as Partial as IBeaconChain; - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - for (const [testCaseIndex, testCase] of testCases.entries()) { - const {phase0Result, phase1Result, seenAttesters} = testCase; - it(`test case ${testCaseIndex}`, async () => { - const phase0Results: Promise[] = []; - for (const [i, isValid] of phase0Result.entries()) { - const signatureSet = { - type: SignatureSetType.single, - pubkey: getKeypair(i).publicKey, - signingRoot, - signature: getKeypair(i).secretKey.sign(signingRoot).toBytes(), - }; - if (isValid) { - if (!phase1Result[i]) { - // invalid signature - signatureSet.signature = getKeypair(2023).secretKey.sign(signingRoot).toBytes(); - } - phase0Results.push( - Promise.resolve({ - attestation: ssz.phase0.Attestation.defaultValue(), - signatureSet, - validatorIndex: i, - } as Partial as Step0Result) - ); - } else { - phase0Results.push( - Promise.reject( - new AttestationError(GossipAction.REJECT, { - code: AttestationErrorCode.BAD_TARGET_EPOCH, - }) - ) - ); - } - } - - let callIndex = 0; - const phase0ValidationFn = (): Promise => { - const result = phase0Results[callIndex]; - callIndex++; - return result; - }; - await validateGossipAttestationsSameAttData(ForkName.phase0, chain, new Array(5).fill({}), 0, phase0ValidationFn); - for (let validatorIndex = 0; validatorIndex < phase0Result.length; validatorIndex++) { - if (seenAttesters.includes(validatorIndex)) { - expect(chain.seenAttesters.isKnown(0, validatorIndex)).toBe(true); - } else { - expect(chain.seenAttesters.isKnown(0, validatorIndex)).toBe(false); - } - } - }); // end test case - } -}); - -describe("validateAttestation", () => { - const vc = 64; - const stateSlot = 100; - - const UNKNOWN_ROOT = Buffer.alloc(32, 1); - const KNOWN_TARGET_ROOT = Buffer.alloc(32, 0xd0); - const KNOWN_BEACON_BLOCK_ROOT = Buffer.alloc(32, 0xd1); - - const getState = memoOnce(() => generateTestCachedBeaconStateOnlyValidators({vc, slot: stateSlot})); - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - function getValidData(opts?: Partial) { - return getAttestationValidData({ - currentSlot: stateSlot, - attSlot: opts?.currentSlot ?? stateSlot, - attIndex: 1, - bitIndex: 1, - targetRoot: KNOWN_TARGET_ROOT, - beaconBlockRoot: KNOWN_BEACON_BLOCK_ROOT, - state: getState(), - ...opts, - }); - } - - it("Valid", async () => { - const {chain, attestation} = getValidData(); - - const fork = chain.config.getForkName(stateSlot); - await validateApiAttestation(fork, chain, {attestation, serializedData: null}); - }); - - it("INVALID_SERIALIZED_BYTES_ERROR_CODE", async () => { - const {chain, subnet} = getValidData(); - await expectGossipError( - chain, - {attestation: null, serializedData: Buffer.alloc(0), attSlot: 0, attDataBase64: "invalid"}, - subnet, - GossipErrorCode.INVALID_SERIALIZED_BYTES_ERROR_CODE - ); - }); - - it("BAD_TARGET_EPOCH", async () => { - const {chain, attestation, subnet} = getValidData(); - - // Change target epoch to it doesn't match data.slot - attestation.data.target.epoch += 1; - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.BAD_TARGET_EPOCH); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.BAD_TARGET_EPOCH - ); - }); - - it("PAST_SLOT", async () => { - // Set attestation at a very old slot - const {chain, attestation, subnet} = getValidData({attSlot: stateSlot - SLOTS_PER_EPOCH - 3}); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.PAST_SLOT); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.PAST_SLOT - ); - }); - - it("FUTURE_SLOT", async () => { - // Set attestation to a future slot - const {chain, attestation, subnet} = getValidData({attSlot: stateSlot + 2}); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.FUTURE_SLOT); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.FUTURE_SLOT - ); - }); - - it("NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - 0 bits", async () => { - // Unset the single aggregationBits - const bitIndex = 1; - const {chain, attestation, subnet} = getValidData({bitIndex}); - attestation.aggregationBits.set(bitIndex, false); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError( - chain, - {attestation, serializedData: null}, - AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - ); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - ); - }); - - it("NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - 2 bits", async () => { - // Set an extra bit in the attestation - const bitIndex = 1; - const {chain, attestation, subnet} = getValidData({bitIndex}); - attestation.aggregationBits.set(bitIndex + 1, true); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - ); - }); - - it("UNKNOWN_BEACON_BLOCK_ROOT", async () => { - const {chain, attestation, subnet} = getValidData(); - // Set beaconBlockRoot to a root not known by the fork choice - attestation.data.beaconBlockRoot = UNKNOWN_ROOT; - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError( - chain, - {attestation, serializedData: null}, - AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT - ); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT - ); - }); - - it("INVALID_TARGET_ROOT", async () => { - const {chain, attestation, subnet} = getValidData(); - // Set target.root to an unknown root - attestation.data.target.root = UNKNOWN_ROOT; - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.INVALID_TARGET_ROOT); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.INVALID_TARGET_ROOT - ); - }); - - it("WRONG_NUMBER_OF_AGGREGATION_BITS", async () => { - const {chain, attestation, subnet} = getValidData(); - // Increase the length of aggregationBits beyond the committee size - attestation.aggregationBits = new BitArray( - attestation.aggregationBits.uint8Array, - attestation.aggregationBits.bitLen + 1 - ); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError( - chain, - {attestation, serializedData: null}, - AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS - ); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS - ); - }); - - it("INVALID_SUBNET_ID", async () => { - const {chain, attestation, subnet} = getValidData(); - // Pass a different subnet value than the correct one - const invalidSubnet = subnet === 0 ? 1 : 0; - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - invalidSubnet, - AttestationErrorCode.INVALID_SUBNET_ID - ); - }); - - it("ATTESTATION_ALREADY_KNOWN", async () => { - const {chain, attestation, subnet, validatorIndex} = getValidData(); - // Register attester as already seen - chain.seenAttesters.add(attestation.data.target.epoch, validatorIndex); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.ATTESTATION_ALREADY_KNOWN); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.ATTESTATION_ALREADY_KNOWN - ); - }); - - it("INVALID_SIGNATURE", async () => { - const bitIndex = 1; - const {chain, attestation, subnet} = getValidData({bitIndex}); - // Change the bit index so the signature is validated against a different pubkey - attestation.aggregationBits.set(bitIndex, false); - attestation.aggregationBits.set(bitIndex + 1, true); - const serializedData = ssz.phase0.Attestation.serialize(attestation); - - await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.INVALID_SIGNATURE); - await expectGossipError( - chain, - { - attestation: null, - serializedData, - attSlot: attestation.data.slot, - attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), - }, - subnet, - AttestationErrorCode.INVALID_SIGNATURE - ); - }); - - /** Alias to reduce code duplication */ - async function expectApiError( - chain: IBeaconChain, - attestationOrBytes: ApiAttestation, - errorCode: string - ): Promise { - const fork = chain.config.getForkName(stateSlot); - await expectRejectedWithLodestarError(validateApiAttestation(fork, chain, attestationOrBytes), errorCode); - } - - async function expectGossipError( - chain: IBeaconChain, - attestationOrBytes: GossipAttestation, - subnet: number, - errorCode: string - ): Promise { - const fork = chain.config.getForkName(stateSlot); - await expectRejectedWithLodestarError(validateAttestation(fork, chain, attestationOrBytes, subnet), errorCode); - } -}); - -describe("getShufflingForAttestationVerification", () => { - let regenStub: MockedBeaconChain["regen"]; - let forkchoiceStub: MockedBeaconChain["forkChoice"]; - let shufflingCacheStub: MockedBeaconChain["shufflingCache"]; - let chain: MockedBeaconChain; - - beforeEach(() => { - chain = getMockedBeaconChain(); - regenStub = chain.regen; - forkchoiceStub = chain.forkChoice; - shufflingCacheStub = chain.shufflingCache; - vi.spyOn(regenStub, "getBlockSlotState"); - vi.spyOn(regenStub, "getState"); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - const attEpoch = 1000; - const blockRoot = "0xd76aed834b4feef32efb53f9076e407c0d344cfdb70f0a770fa88416f70d304d"; - - it("block epoch is the same to attestation epoch", async () => { - const headSlot = computeStartSlotAtEpoch(attEpoch); - const attHeadBlock = { - slot: headSlot, - stateRoot: ZERO_HASH_HEX, - blockRoot, - } as Partial as ProtoBlock; - const previousDependentRoot = "0xa916b57729dbfb89a082820e0eb2b669d9d511a675d3d8c888b2f300f10b0bdf"; - forkchoiceStub.getDependentRoot.mockImplementationOnce((block, epochDiff) => { - if (block === attHeadBlock && epochDiff === EpochDifference.previous) { - return previousDependentRoot; - } else { - throw new Error("Unexpected input"); - } - }); - const expectedShuffling = {epoch: attEpoch} as EpochShuffling; - shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { - if (epoch === attEpoch && root === previousDependentRoot) { - return Promise.resolve(expectedShuffling); - } else { - return Promise.resolve(null); - } - }); - const resultShuffling = await getShufflingForAttestationVerification( - chain, - attEpoch, - attHeadBlock, - RegenCaller.validateGossipAttestation - ); - expect(resultShuffling).to.be.deep.equal(expectedShuffling); - }); - - it("block epoch is previous attestation epoch", async () => { - const headSlot = computeStartSlotAtEpoch(attEpoch - 1); - const attHeadBlock = { - slot: headSlot, - stateRoot: ZERO_HASH_HEX, - blockRoot, - } as Partial as ProtoBlock; - const currentDependentRoot = "0xa916b57729dbfb89a082820e0eb2b669d9d511a675d3d8c888b2f300f10b0bdf"; - forkchoiceStub.getDependentRoot.mockImplementationOnce((block, epochDiff) => { - if (block === attHeadBlock && epochDiff === EpochDifference.current) { - return currentDependentRoot; - } else { - throw new Error("Unexpected input"); - } - }); - const expectedShuffling = {epoch: attEpoch} as EpochShuffling; - shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { - if (epoch === attEpoch && root === currentDependentRoot) { - return Promise.resolve(expectedShuffling); - } else { - return Promise.resolve(null); - } - }); - const resultShuffling = await getShufflingForAttestationVerification( - chain, - attEpoch, - attHeadBlock, - RegenCaller.validateGossipAttestation - ); - expect(resultShuffling).to.be.deep.equal(expectedShuffling); - }); - - it("block epoch is attestation epoch - 2", async () => { - const headSlot = computeStartSlotAtEpoch(attEpoch - 2); - const attHeadBlock = { - slot: headSlot, - stateRoot: ZERO_HASH_HEX, - blockRoot, - } as Partial as ProtoBlock; - const expectedShuffling = {epoch: attEpoch} as EpochShuffling; - let callCount = 0; - shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { - if (epoch === attEpoch && root === blockRoot) { - if (callCount === 0) { - callCount++; - return Promise.resolve(null); - } else { - return Promise.resolve(expectedShuffling); - } - } else { - return Promise.resolve(null); - } - }); - chain.regenStateForAttestationVerification.mockImplementationOnce(() => Promise.resolve(expectedShuffling)); - - const resultShuffling = await getShufflingForAttestationVerification( - chain, - attEpoch, - attHeadBlock, - RegenCaller.validateGossipAttestation - ); - // sandbox.assert.notCalled(forkchoiceStub.getDependentRoot); - expect(forkchoiceStub.getDependentRoot).not.toHaveBeenCalledTimes(1); - expect(resultShuffling).to.be.deep.equal(expectedShuffling); - }); - - it("block epoch is attestation epoch + 1", async () => { - const headSlot = computeStartSlotAtEpoch(attEpoch + 1); - const attHeadBlock = { - slot: headSlot, - stateRoot: ZERO_HASH_HEX, - blockRoot, - } as Partial as ProtoBlock; - try { - await getShufflingForAttestationVerification( - chain, - attEpoch, - attHeadBlock, - RegenCaller.validateGossipAttestation - ); - expect.fail("Expect error because attestation epoch is greater than block epoch"); - } catch (e) { - expect(e instanceof Error).to.be.true; - } - }); -}); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts new file mode 100644 index 000000000000..a0eb147db8e8 --- /dev/null +++ b/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts @@ -0,0 +1,150 @@ +import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; +// We need to import the mock before the packages +// eslint-disable-next-line import/order +import {MockedBeaconChain, getMockedBeaconChain} from "../../../../mocks/mockedBeaconChain.js"; +import {EpochShuffling, computeStartSlotAtEpoch} from "@lodestar/state-transition"; +import {EpochDifference, ProtoBlock} from "@lodestar/fork-choice"; +import {RegenCaller} from "../../../../../src/chain/regen/interface.js"; +import {getShufflingForAttestationVerification} from "../../../../../src/chain/validation/index.js"; +import {ZERO_HASH_HEX} from "../../../../../src/constants/constants.js"; + +describe("getShufflingForAttestationVerification", () => { + let chain: MockedBeaconChain; + let regenStub: MockedBeaconChain["regen"]; + let forkchoiceStub: MockedBeaconChain["forkChoice"]; + let shufflingCacheStub: MockedBeaconChain["shufflingCache"]; + + beforeEach(() => { + chain = getMockedBeaconChain(); + regenStub = chain.regen; + forkchoiceStub = chain.forkChoice; + shufflingCacheStub = chain.shufflingCache; + vi.spyOn(regenStub, "getBlockSlotState"); + vi.spyOn(regenStub, "getState"); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + const attEpoch = 1000; + const blockRoot = "0xd76aed834b4feef32efb53f9076e407c0d344cfdb70f0a770fa88416f70d304d"; + + it("block epoch is the same to attestation epoch", async () => { + const headSlot = computeStartSlotAtEpoch(attEpoch); + const attHeadBlock = { + slot: headSlot, + stateRoot: ZERO_HASH_HEX, + blockRoot, + } as Partial; + const previousDependentRoot = "0xa916b57729dbfb89a082820e0eb2b669d9d511a675d3d8c888b2f300f10b0bdf"; + forkchoiceStub.getDependentRoot.mockImplementationOnce((block, epochDiff) => { + if (block === attHeadBlock && epochDiff === EpochDifference.previous) { + return previousDependentRoot; + } else { + throw new Error("Unexpected input"); + } + }); + const expectedShuffling = {epoch: attEpoch} as EpochShuffling; + shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { + if (epoch === attEpoch && root === previousDependentRoot) { + return Promise.resolve(expectedShuffling); + } else { + return Promise.resolve(null); + } + }); + const resultShuffling = await getShufflingForAttestationVerification( + chain, + attEpoch, + attHeadBlock as ProtoBlock, + RegenCaller.validateGossipAttestation + ); + expect(resultShuffling).toEqual(expectedShuffling); + }); + + it("block epoch is previous attestation epoch", async () => { + const headSlot = computeStartSlotAtEpoch(attEpoch - 1); + const attHeadBlock = { + slot: headSlot, + stateRoot: ZERO_HASH_HEX, + blockRoot, + } as Partial; + const currentDependentRoot = "0xa916b57729dbfb89a082820e0eb2b669d9d511a675d3d8c888b2f300f10b0bdf"; + forkchoiceStub.getDependentRoot.mockImplementationOnce((block, epochDiff) => { + if (block === attHeadBlock && epochDiff === EpochDifference.current) { + return currentDependentRoot; + } else { + throw new Error("Unexpected input"); + } + }); + const expectedShuffling = {epoch: attEpoch} as EpochShuffling; + shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { + if (epoch === attEpoch && root === currentDependentRoot) { + return Promise.resolve(expectedShuffling); + } else { + return Promise.resolve(null); + } + }); + const resultShuffling = await getShufflingForAttestationVerification( + chain, + attEpoch, + attHeadBlock as ProtoBlock, + RegenCaller.validateGossipAttestation + ); + expect(resultShuffling).toEqual(expectedShuffling); + }); + + it("block epoch is attestation epoch - 2", async () => { + const headSlot = computeStartSlotAtEpoch(attEpoch - 2); + const attHeadBlock = { + slot: headSlot, + stateRoot: ZERO_HASH_HEX, + blockRoot, + } as Partial; + const expectedShuffling = {epoch: attEpoch} as EpochShuffling; + let callCount = 0; + shufflingCacheStub.get.mockImplementationOnce((epoch, root) => { + if (epoch === attEpoch && root === blockRoot) { + if (callCount === 0) { + callCount++; + return Promise.resolve(null); + } else { + return Promise.resolve(expectedShuffling); + } + } else { + return Promise.resolve(null); + } + }); + chain.regenStateForAttestationVerification.mockImplementationOnce(() => Promise.resolve(expectedShuffling)); + + const resultShuffling = await getShufflingForAttestationVerification( + chain, + attEpoch, + attHeadBlock as ProtoBlock, + RegenCaller.validateGossipAttestation + ); + // sandbox.assert.notCalled(forkchoiceStub.getDependentRoot); + expect(forkchoiceStub.getDependentRoot).not.toHaveBeenCalledTimes(1); + expect(resultShuffling).toEqual(expectedShuffling); + }); + + it("block epoch is attestation epoch + 1", async () => { + const headSlot = computeStartSlotAtEpoch(attEpoch + 1); + const attHeadBlock = { + slot: headSlot, + stateRoot: ZERO_HASH_HEX, + blockRoot, + } as Partial; + try { + await getShufflingForAttestationVerification( + chain, + attEpoch, + attHeadBlock as ProtoBlock, + RegenCaller.validateGossipAttestation + ); + expect.fail("Expect error because attestation epoch is greater than block epoch"); + } catch (e) { + expect(e instanceof Error).toBeTruthy(); + } + }); +}); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts new file mode 100644 index 000000000000..56aab699f4f7 --- /dev/null +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts @@ -0,0 +1,316 @@ +import {BitArray} from "@chainsafe/ssz"; +import {describe, it} from "vitest"; +import {SLOTS_PER_EPOCH} from "@lodestar/params"; +import {ssz} from "@lodestar/types"; +// eslint-disable-next-line import/no-relative-packages +import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../../state-transition/test/perf/util.js"; +import {AttestationErrorCode, GossipErrorCode} from "../../../../../src/chain/errors/index.js"; +import {IBeaconChain} from "../../../../../src/chain/index.js"; +import { + ApiAttestation, + GossipAttestation, + validateApiAttestation, + validateAttestation, +} from "../../../../../src/chain/validation/index.js"; +import {getAttDataBase64FromAttestationSerialized} from "../../../../../src/util/sszBytes.js"; +import {memoOnce} from "../../../../utils/cache.js"; +import {expectRejectedWithLodestarError} from "../../../../utils/errors.js"; +import {AttestationValidDataOpts, getAttestationValidData} from "../../../../utils/validationData/attestation.js"; + +describe("validateAttestation", () => { + const vc = 64; + const stateSlot = 100; + + const UNKNOWN_ROOT = Buffer.alloc(32, 1); + const KNOWN_TARGET_ROOT = Buffer.alloc(32, 0xd0); + const KNOWN_BEACON_BLOCK_ROOT = Buffer.alloc(32, 0xd1); + + const getState = memoOnce(() => generateTestCachedBeaconStateOnlyValidators({vc, slot: stateSlot})); + + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + function getValidData(opts?: Partial) { + return getAttestationValidData({ + currentSlot: stateSlot, + attSlot: opts?.currentSlot ?? stateSlot, + attIndex: 1, + bitIndex: 1, + targetRoot: KNOWN_TARGET_ROOT, + beaconBlockRoot: KNOWN_BEACON_BLOCK_ROOT, + state: getState(), + ...opts, + }); + } + + it("Valid", async () => { + const {chain, attestation} = getValidData(); + + const fork = chain.config.getForkName(stateSlot); + await validateApiAttestation(fork, chain, {attestation, serializedData: null}); + }); + + it("INVALID_SERIALIZED_BYTES_ERROR_CODE", async () => { + const {chain, subnet} = getValidData(); + await expectGossipError( + chain, + {attestation: null, serializedData: Buffer.alloc(0), attSlot: 0, attDataBase64: "invalid"}, + subnet, + GossipErrorCode.INVALID_SERIALIZED_BYTES_ERROR_CODE + ); + }); + + it("BAD_TARGET_EPOCH", async () => { + const {chain, attestation, subnet} = getValidData(); + + // Change target epoch to it doesn't match data.slot + attestation.data.target.epoch += 1; + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.BAD_TARGET_EPOCH); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.BAD_TARGET_EPOCH + ); + }); + + it("PAST_SLOT", async () => { + // Set attestation at a very old slot + const {chain, attestation, subnet} = getValidData({attSlot: stateSlot - SLOTS_PER_EPOCH - 3}); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.PAST_SLOT); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.PAST_SLOT + ); + }); + + it("FUTURE_SLOT", async () => { + // Set attestation to a future slot + const {chain, attestation, subnet} = getValidData({attSlot: stateSlot + 2}); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.FUTURE_SLOT); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.FUTURE_SLOT + ); + }); + + it("NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - 0 bits", async () => { + // Unset the single aggregationBits + const bitIndex = 1; + const {chain, attestation, subnet} = getValidData({bitIndex}); + attestation.aggregationBits.set(bitIndex, false); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError( + chain, + {attestation, serializedData: null}, + AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET + ); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET + ); + }); + + it("NOT_EXACTLY_ONE_AGGREGATION_BIT_SET - 2 bits", async () => { + // Set an extra bit in the attestation + const bitIndex = 1; + const {chain, attestation, subnet} = getValidData({bitIndex}); + attestation.aggregationBits.set(bitIndex + 1, true); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET + ); + }); + + it("UNKNOWN_BEACON_BLOCK_ROOT", async () => { + const {chain, attestation, subnet} = getValidData(); + // Set beaconBlockRoot to a root not known by the fork choice + attestation.data.beaconBlockRoot = UNKNOWN_ROOT; + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError( + chain, + {attestation, serializedData: null}, + AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT + ); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT + ); + }); + + it("INVALID_TARGET_ROOT", async () => { + const {chain, attestation, subnet} = getValidData(); + // Set target.root to an unknown root + attestation.data.target.root = UNKNOWN_ROOT; + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.INVALID_TARGET_ROOT); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.INVALID_TARGET_ROOT + ); + }); + + it("WRONG_NUMBER_OF_AGGREGATION_BITS", async () => { + const {chain, attestation, subnet} = getValidData(); + // Increase the length of aggregationBits beyond the committee size + attestation.aggregationBits = new BitArray( + attestation.aggregationBits.uint8Array, + attestation.aggregationBits.bitLen + 1 + ); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError( + chain, + {attestation, serializedData: null}, + AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS + ); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS + ); + }); + + it("INVALID_SUBNET_ID", async () => { + const {chain, attestation, subnet} = getValidData(); + // Pass a different subnet value than the correct one + const invalidSubnet = subnet === 0 ? 1 : 0; + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + invalidSubnet, + AttestationErrorCode.INVALID_SUBNET_ID + ); + }); + + it("ATTESTATION_ALREADY_KNOWN", async () => { + const {chain, attestation, subnet, validatorIndex} = getValidData(); + // Register attester as already seen + chain.seenAttesters.add(attestation.data.target.epoch, validatorIndex); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.ATTESTATION_ALREADY_KNOWN); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.ATTESTATION_ALREADY_KNOWN + ); + }); + + it("INVALID_SIGNATURE", async () => { + const bitIndex = 1; + const {chain, attestation, subnet} = getValidData({bitIndex}); + // Change the bit index so the signature is validated against a different pubkey + attestation.aggregationBits.set(bitIndex, false); + attestation.aggregationBits.set(bitIndex + 1, true); + const serializedData = ssz.phase0.Attestation.serialize(attestation); + + await expectApiError(chain, {attestation, serializedData: null}, AttestationErrorCode.INVALID_SIGNATURE); + await expectGossipError( + chain, + { + attestation: null, + serializedData, + attSlot: attestation.data.slot, + attDataBase64: getAttDataBase64FromAttestationSerialized(serializedData), + }, + subnet, + AttestationErrorCode.INVALID_SIGNATURE + ); + }); + + /** Alias to reduce code duplication */ + async function expectApiError( + chain: IBeaconChain, + attestationOrBytes: ApiAttestation, + errorCode: string + ): Promise { + const fork = chain.config.getForkName(stateSlot); + await expectRejectedWithLodestarError(validateApiAttestation(fork, chain, attestationOrBytes), errorCode); + } + + async function expectGossipError( + chain: IBeaconChain, + attestationOrBytes: GossipAttestation, + subnet: number, + errorCode: string + ): Promise { + const fork = chain.config.getForkName(stateSlot); + await expectRejectedWithLodestarError(validateAttestation(fork, chain, attestationOrBytes, subnet), errorCode); + } +}); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts new file mode 100644 index 000000000000..29b9ba3e1912 --- /dev/null +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts @@ -0,0 +1,128 @@ +import bls from "@chainsafe/bls"; +import type {PublicKey, SecretKey} from "@chainsafe/bls/types"; +import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; +import {ForkName} from "@lodestar/params"; +import {SignatureSetType} from "@lodestar/state-transition"; +import {ssz} from "@lodestar/types"; +// eslint-disable-next-line import/no-relative-packages +import {BlsSingleThreadVerifier} from "../../../../../src/chain/bls/singleThread.js"; +import {AttestationError, AttestationErrorCode, GossipAction} from "../../../../../src/chain/errors/index.js"; +import {IBeaconChain} from "../../../../../src/chain/index.js"; +import {SeenAttesters} from "../../../../../src/chain/seenCache/seenAttesters.js"; +import {Step0Result, validateGossipAttestationsSameAttData} from "../../../../../src/chain/validation/index.js"; + +describe("validateGossipAttestationsSameAttData", () => { + // phase0Result specifies whether the attestation is valid in phase0 + // phase1Result specifies signature verification + const testCases: {phase0Result: boolean[]; phase1Result: boolean[]; seenAttesters: number[]}[] = [ + { + phase0Result: [true, true, true, true, true], + phase1Result: [true, true, true, true, true], + seenAttesters: [0, 1, 2, 3, 4], + }, + { + phase0Result: [false, true, true, true, true], + phase1Result: [true, false, true, true, true], + seenAttesters: [2, 3, 4], + }, + { + phase0Result: [false, false, true, true, true], + phase1Result: [true, false, false, true, true], + seenAttesters: [3, 4], + }, + { + phase0Result: [false, false, true, true, true], + phase1Result: [true, false, false, true, false], + seenAttesters: [3], + }, + { + phase0Result: [false, false, true, true, true], + phase1Result: [true, true, false, false, false], + seenAttesters: [], + }, + ]; + + type Keypair = {publicKey: PublicKey; secretKey: SecretKey}; + const keypairs = new Map(); + function getKeypair(i: number): Keypair { + let keypair = keypairs.get(i); + if (!keypair) { + const bytes = new Uint8Array(32); + const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + dataView.setUint32(0, i + 1, true); + const secretKey = bls.SecretKey.fromBytes(bytes); + const publicKey = secretKey.toPublicKey(); + keypair = {secretKey, publicKey}; + keypairs.set(i, keypair); + } + return keypair; + } + + let chain: IBeaconChain; + const signingRoot = Buffer.alloc(32, 1); + + beforeEach(() => { + chain = { + bls: new BlsSingleThreadVerifier({metrics: null}), + seenAttesters: new SeenAttesters(), + opts: { + minSameMessageSignatureSetsToBatch: 2, + } as IBeaconChain["opts"], + } as Partial as IBeaconChain; + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + for (const [testCaseIndex, testCase] of testCases.entries()) { + const {phase0Result, phase1Result, seenAttesters} = testCase; + it(`test case ${testCaseIndex}`, async () => { + const phase0Results: Promise[] = []; + for (const [i, isValid] of phase0Result.entries()) { + const signatureSet = { + type: SignatureSetType.single, + pubkey: getKeypair(i).publicKey, + signingRoot, + signature: getKeypair(i).secretKey.sign(signingRoot).toBytes(), + }; + if (isValid) { + if (!phase1Result[i]) { + // invalid signature + signatureSet.signature = getKeypair(2023).secretKey.sign(signingRoot).toBytes(); + } + phase0Results.push( + Promise.resolve({ + attestation: ssz.phase0.Attestation.defaultValue(), + signatureSet, + validatorIndex: i, + } as Partial as Step0Result) + ); + } else { + phase0Results.push( + Promise.reject( + new AttestationError(GossipAction.REJECT, { + code: AttestationErrorCode.BAD_TARGET_EPOCH, + }) + ) + ); + } + } + + let callIndex = 0; + const phase0ValidationFn = (): Promise => { + const result = phase0Results[callIndex]; + callIndex++; + return result; + }; + await validateGossipAttestationsSameAttData(ForkName.phase0, chain, new Array(5).fill({}), 0, phase0ValidationFn); + for (let validatorIndex = 0; validatorIndex < phase0Result.length; validatorIndex++) { + if (seenAttesters.includes(validatorIndex)) { + expect(chain.seenAttesters.isKnown(0, validatorIndex)).toBe(true); + } else { + expect(chain.seenAttesters.isKnown(0, validatorIndex)).toBe(false); + } + } + }); // end test case + } +}); diff --git a/packages/beacon-node/test/unit/chain/validation/attesterSlashing.test.ts b/packages/beacon-node/test/unit/chain/validation/attesterSlashing.test.ts index dcb07e5998ec..629753824669 100644 --- a/packages/beacon-node/test/unit/chain/validation/attesterSlashing.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attesterSlashing.test.ts @@ -1,10 +1,10 @@ import {describe, it, beforeEach, afterEach, vi} from "vitest"; import {phase0, ssz} from "@lodestar/types"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {generateCachedState} from "../../../utils/state.js"; import {validateGossipAttesterSlashing} from "../../../../src/chain/validation/attesterSlashing.js"; import {AttesterSlashingErrorCode} from "../../../../src/chain/errors/attesterSlashingError.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; describe("GossipMessageValidator", () => { let chainStub: MockedBeaconChain; diff --git a/packages/beacon-node/test/unit/chain/validation/block.test.ts b/packages/beacon-node/test/unit/chain/validation/block.test.ts index f1aca0a43cf7..65f8114ebe93 100644 --- a/packages/beacon-node/test/unit/chain/validation/block.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/block.test.ts @@ -1,21 +1,21 @@ -import {Mock, MockedObject, beforeEach, describe, it, vi} from "vitest"; +import {Mock, Mocked, beforeEach, describe, it, vi} from "vitest"; import {config} from "@lodestar/config/default"; import {ProtoBlock} from "@lodestar/fork-choice"; import {ForkName} from "@lodestar/params"; import {allForks, ssz} from "@lodestar/types"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {BlockErrorCode} from "../../../../src/chain/errors/index.js"; import {QueuedStateRegenerator} from "../../../../src/chain/regen/index.js"; import {SeenBlockProposers} from "../../../../src/chain/seenCache/index.js"; import {validateGossipBlock} from "../../../../src/chain/validation/index.js"; import {EMPTY_SIGNATURE, ZERO_HASH} from "../../../../src/constants/index.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; import {generateCachedState} from "../../../utils/state.js"; describe("gossip block validation", function () { let chain: MockedBeaconChain; let forkChoice: MockedBeaconChain["forkChoice"]; - let regen: MockedObject; + let regen: Mocked; let verifySignature: Mock<[boolean]>; let job: allForks.SignedBeaconBlock; const proposerIndex = 0; diff --git a/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts b/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts index dd4402255949..f83b900beb69 100644 --- a/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts @@ -14,13 +14,12 @@ import { ForkName, } from "@lodestar/params"; import {createBeaconConfig} from "@lodestar/config"; - +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {generateState} from "../../../utils/state.js"; import {validateGossipBlsToExecutionChange} from "../../../../src/chain/validation/blsToExecutionChange.js"; import {BlsToExecutionChangeErrorCode} from "../../../../src/chain/errors/blsToExecutionChangeError.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; import {createCachedBeaconStateTest} from "../../../utils/cachedBeaconState.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; describe("validate bls to execution change", () => { let chainStub: MockedBeaconChain; diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts index 5e30b13a8861..70dda2535521 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts @@ -5,7 +5,7 @@ import {computeTimeAtSlot} from "@lodestar/state-transition"; import {validateLightClientFinalityUpdate} from "../../../../src/chain/validation/lightClientFinalityUpdate.js"; import {LightClientErrorCode} from "../../../../src/chain/errors/lightClientError.js"; import {IBeaconChain} from "../../../../src/chain/index.js"; -import {getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; +import {getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; describe("Light Client Finality Update validation", function () { const afterEachCallbacks: (() => Promise | void)[] = []; diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts index 0631c01758e2..304db1365fb1 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts @@ -5,7 +5,7 @@ import {computeTimeAtSlot} from "@lodestar/state-transition"; import {validateLightClientOptimisticUpdate} from "../../../../src/chain/validation/lightClientOptimisticUpdate.js"; import {LightClientErrorCode} from "../../../../src/chain/errors/lightClientError.js"; import {IBeaconChain} from "../../../../src/chain/index.js"; -import {getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; +import {getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; describe("Light Client Optimistic Update validation", function () { const afterEachCallbacks: (() => Promise | void)[] = []; diff --git a/packages/beacon-node/test/unit/chain/validation/proposerSlashing.test.ts b/packages/beacon-node/test/unit/chain/validation/proposerSlashing.test.ts index de172c0ec136..f5eb7310a39c 100644 --- a/packages/beacon-node/test/unit/chain/validation/proposerSlashing.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/proposerSlashing.test.ts @@ -1,10 +1,10 @@ import {describe, it, beforeEach, afterEach, vi} from "vitest"; import {phase0, ssz} from "@lodestar/types"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {generateCachedState} from "../../../utils/state.js"; import {ProposerSlashingErrorCode} from "../../../../src/chain/errors/proposerSlashingError.js"; import {validateGossipProposerSlashing} from "../../../../src/chain/validation/proposerSlashing.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; describe("validate proposer slashing", () => { let chainStub: MockedBeaconChain; diff --git a/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts b/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts index 739ab44503c7..b498333ae738 100644 --- a/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts @@ -3,13 +3,13 @@ import {describe, it, expect, afterEach, beforeEach, beforeAll, afterAll, vi, Mo import {altair, Epoch, Slot} from "@lodestar/types"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {createChainForkConfig, defaultChainConfig} from "@lodestar/config"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {SyncCommitteeErrorCode} from "../../../../src/chain/errors/syncCommitteeError.js"; import {validateGossipSyncCommittee} from "../../../../src/chain/validation/syncCommittee.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; import {generateCachedAltairState} from "../../../utils/state.js"; import {SeenSyncCommitteeMessages} from "../../../../src/chain/seenCache/index.js"; import {ZERO_HASH} from "../../../../src/constants/constants.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; // https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/p2p-interface.md describe("Sync Committee Signature validation", function () { diff --git a/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts b/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts index 2933fdc1ef77..3966815c28ce 100644 --- a/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts @@ -11,12 +11,12 @@ import { import {phase0, ssz} from "@lodestar/types"; import {DOMAIN_VOLUNTARY_EXIT, FAR_FUTURE_EPOCH, SLOTS_PER_EPOCH} from "@lodestar/params"; import {createBeaconConfig} from "@lodestar/config"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; import {generateState} from "../../../utils/state.js"; import {validateGossipVoluntaryExit} from "../../../../src/chain/validation/voluntaryExit.js"; import {VoluntaryExitErrorCode} from "../../../../src/chain/errors/voluntaryExitError.js"; import {expectRejectedWithLodestarError} from "../../../utils/errors.js"; import {createCachedBeaconStateTest} from "../../../utils/cachedBeaconState.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../../__mocks__/mockedBeaconChain.js"; describe("validate voluntary exit", () => { let chainStub: MockedBeaconChain; diff --git a/packages/beacon-node/test/unit/db/api/repository.test.ts b/packages/beacon-node/test/unit/db/api/repository.test.ts index 713ed0df88f2..07c199632125 100644 --- a/packages/beacon-node/test/unit/db/api/repository.test.ts +++ b/packages/beacon-node/test/unit/db/api/repository.test.ts @@ -87,18 +87,18 @@ describe("database repository", function () { it("should store with hashTreeRoot as id", async function () { const item = {bool: true, bytes: Buffer.alloc(32)}; - expect(repository.add(item)).not.rejects; + await expect(repository.add(item)).resolves.toBeUndefined(); expect(controller.put).toHaveBeenCalledTimes(1); }); it("should store with given id", async function () { const item = {bool: true, bytes: Buffer.alloc(32)}; - expect(repository.put("1", item)).not.rejects; + await expect(repository.put("1", item)).resolves.toBeUndefined(); expect(controller.put).toHaveBeenCalledTimes(1); }); it("should delete", async function () { - expect(repository.delete("1")).not.rejects; + await expect(repository.delete("1")).resolves.toBeUndefined(); expect(controller.delete).toHaveBeenCalledTimes(1); }); diff --git a/packages/beacon-node/test/unit/eth1/eth1DepositDataTracker.test.ts b/packages/beacon-node/test/unit/eth1/eth1DepositDataTracker.test.ts index 37e4b84a3d68..d0bd3faffcf8 100644 --- a/packages/beacon-node/test/unit/eth1/eth1DepositDataTracker.test.ts +++ b/packages/beacon-node/test/unit/eth1/eth1DepositDataTracker.test.ts @@ -6,7 +6,7 @@ import {Eth1Provider} from "../../../src/eth1/provider/eth1Provider.js"; import {testLogger} from "../../utils/logger.js"; import {defaultEth1Options} from "../../../src/eth1/options.js"; import {BeaconDb} from "../../../src/db/beacon.js"; -import {getMockedBeaconDb} from "../../__mocks__/mockedBeaconDb.js"; +import {getMockedBeaconDb} from "../../mocks/mockedBeaconDb.js"; describe("Eth1DepositDataTracker", function () { const controller = new AbortController(); diff --git a/packages/beacon-node/test/unit/monitoring/service.test.ts b/packages/beacon-node/test/unit/monitoring/service.test.ts index 068f35634f81..c5911ba4b113 100644 --- a/packages/beacon-node/test/unit/monitoring/service.test.ts +++ b/packages/beacon-node/test/unit/monitoring/service.test.ts @@ -5,7 +5,7 @@ import {RegistryMetricCreator} from "../../../src/index.js"; import {MonitoringService} from "../../../src/monitoring/service.js"; import {MonitoringOptions} from "../../../src/monitoring/options.js"; import {sleep} from "../../utils/sleep.js"; -import {MockedLogger, getMockedLogger} from "../../__mocks__/loggerMock.js"; +import {MockedLogger, getMockedLogger} from "../../mocks/loggerMock.js"; import {startRemoteService, remoteServiceRoutes, remoteServiceError} from "./remoteService.js"; describe("monitoring / service", () => { diff --git a/packages/beacon-node/test/unit/network/peers/priorization.test.ts b/packages/beacon-node/test/unit/network/peers/priorization.test.ts index cc9ef9b7d711..3ec770051275 100644 --- a/packages/beacon-node/test/unit/network/peers/priorization.test.ts +++ b/packages/beacon-node/test/unit/network/peers/priorization.test.ts @@ -14,6 +14,7 @@ import {RequestedSubnet} from "../../../../src/network/peers/utils/index.js"; type Result = ReturnType; +// eslint-disable-next-line vitest/valid-describe-callback describe("network / peers / priorization", async () => { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { @@ -263,6 +264,7 @@ describe("network / peers / priorization", async () => { } }); +// eslint-disable-next-line vitest/valid-describe-callback describe("sortPeersToPrune", async function () { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { diff --git a/packages/beacon-node/test/unit/network/peers/score.test.ts b/packages/beacon-node/test/unit/network/peers/score.test.ts index 9c5402b5c888..df842f9a1310 100644 --- a/packages/beacon-node/test/unit/network/peers/score.test.ts +++ b/packages/beacon-node/test/unit/network/peers/score.test.ts @@ -9,10 +9,10 @@ import { RealScore, } from "../../../../src/network/peers/score/index.js"; -vi.mock("../../../../src/network/peers/score/index.js", async (requireActual) => { - const mod = await requireActual(); +vi.mock("../../../../src/network/peers/score/index.js", async (importActual) => { + const mod = await importActual(); - mod.PeerRpcScoreStore.prototype.updateGossipsubScore = vi.fn(); + vi.spyOn(mod.PeerRpcScoreStore.prototype, "updateGossipsubScore").mockImplementation(() => {}); return { ...mod, diff --git a/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts b/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts index fb2fd7e78fdb..1c293fbb7640 100644 --- a/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts +++ b/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts @@ -112,7 +112,7 @@ describe("AttnetsService", function () { expect(metadata.seqNumber).toBe(BigInt(1)); expect(EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION * SLOTS_PER_EPOCH).toBeGreaterThan(150); vi.advanceTimersByTime(150 * SLOTS_PER_EPOCH * SECONDS_PER_SLOT * 1000); - expect(gossipStub.unsubscribeTopic).toHaveBeenCalled(); + expect(gossipStub.unsubscribeTopic).toHaveBeenCalledOnce(); // subscribe then unsubscribe expect(metadata.seqNumber).toBe(BigInt(2)); }); @@ -127,8 +127,8 @@ describe("AttnetsService", function () { vi.advanceTimersByTime(SLOTS_PER_EPOCH * SECONDS_PER_SLOT * 1000); } // may call 2 times, 1 for committee subnet, 1 for random subnet - expect(gossipStub.unsubscribeTopic).toHaveBeenCalled(); - // rebalance twice + expect(gossipStub.unsubscribeTopic).toHaveBeenCalledWith(expect.any(Object)); + // rebalanced twice expect(metadata.seqNumber).toBe(BigInt(2)); }); diff --git a/packages/beacon-node/test/unit/sync/backfill/verify.test.ts b/packages/beacon-node/test/unit/sync/backfill/verify.test.ts index ebfe85eab09f..08ffdc4c3b02 100644 --- a/packages/beacon-node/test/unit/sync/backfill/verify.test.ts +++ b/packages/beacon-node/test/unit/sync/backfill/verify.test.ts @@ -25,7 +25,9 @@ describe("backfill sync - verify block sequence", function () { it("should verify valid chain of blocks", function () { const blocks = getBlocks(); - expect(() => verifyBlockSequence(beaconConfig, blocks.slice(0, 2), blocks[2].data.message.parentRoot)).to.not.throw; + expect(() => + verifyBlockSequence(beaconConfig, blocks.slice(0, 2), blocks[2].data.message.parentRoot) + ).not.toThrow(); }); it("should fail with sequence not anchored", function () { diff --git a/packages/beacon-node/test/unit/sync/range/batch.test.ts b/packages/beacon-node/test/unit/sync/range/batch.test.ts index acbfdcdb938b..caf8d5ea82e4 100644 --- a/packages/beacon-node/test/unit/sync/range/batch.test.ts +++ b/packages/beacon-node/test/unit/sync/range/batch.test.ts @@ -7,7 +7,7 @@ import {Batch, BatchStatus, BatchErrorCode, BatchError} from "../../../../src/sy import {EPOCHS_PER_BATCH} from "../../../../src/sync/constants.js"; import {BlockSource, getBlockInput} from "../../../../src/chain/blocks/types.js"; import {validPeerIdStr} from "../../../utils/peer.js"; -describe("sync / range / batch", async () => { +describe("sync / range / batch", () => { // Common mock data const startEpoch = 0; const peer = validPeerIdStr; diff --git a/packages/beacon-node/test/unit/sync/unknownBlock.test.ts b/packages/beacon-node/test/unit/sync/unknownBlock.test.ts index 1da15ce7553b..a0a8be65dd28 100644 --- a/packages/beacon-node/test/unit/sync/unknownBlock.test.ts +++ b/packages/beacon-node/test/unit/sync/unknownBlock.test.ts @@ -6,18 +6,18 @@ import {createChainForkConfig} from "@lodestar/config"; import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice"; import {ssz} from "@lodestar/types"; import {notNullish, sleep} from "@lodestar/utils"; +import {MockedBeaconChain, getMockedBeaconChain} from "../../mocks/mockedBeaconChain.js"; import {IBeaconChain} from "../../../src/chain/index.js"; import {INetwork, NetworkEvent, NetworkEventBus, PeerAction} from "../../../src/network/index.js"; import {UnknownBlockSync} from "../../../src/sync/unknownBlock.js"; import {testLogger} from "../../utils/logger.js"; import {getRandPeerIdStr} from "../../utils/peer.js"; import {BlockSource, getBlockInput} from "../../../src/chain/blocks/types.js"; -import {ClockStopped} from "../../utils/mocks/clock.js"; +import {ClockStopped} from "../../mocks/clock.js"; import {SeenBlockProposers} from "../../../src/chain/seenCache/seenBlockProposers.js"; import {BlockError, BlockErrorCode} from "../../../src/chain/errors/blockError.js"; import {defaultSyncOptions} from "../../../src/sync/options.js"; import {ZERO_HASH} from "../../../src/constants/constants.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../__mocks__/mockedBeaconChain.js"; describe("sync by UnknownBlockSync", () => { const logger = testLogger(); @@ -199,7 +199,7 @@ describe("sync by UnknownBlockSync", () => { const [_, requestedRoots] = await sendBeaconBlocksByRootPromise; await sleep(200); // should not send the invalid root block to chain - expect(processBlockSpy).toBeCalled(); + expect(processBlockSpy).toHaveBeenCalledOnce(); for (const requestedRoot of requestedRoots) { expect(syncService["pendingBlocks"].get(toHexString(requestedRoot))?.downloadAttempts).toEqual(1); } diff --git a/packages/beacon-node/test/unit/util/dependentRoot.test.ts b/packages/beacon-node/test/unit/util/dependentRoot.test.ts index e2f11acc3eba..e7923f111d0b 100644 --- a/packages/beacon-node/test/unit/util/dependentRoot.test.ts +++ b/packages/beacon-node/test/unit/util/dependentRoot.test.ts @@ -1,11 +1,12 @@ -import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; -import {EpochDifference, ProtoBlock} from "@lodestar/fork-choice"; +import {describe, it, expect, beforeEach, afterEach, vi, Mocked} from "vitest"; +import {EpochDifference, ProtoBlock, ForkChoice} from "@lodestar/fork-choice"; import {computeEpochAtSlot} from "@lodestar/state-transition"; import {getShufflingDependentRoot} from "../../../src/util/dependentRoot.js"; -import {MockedBeaconChain, getMockedBeaconChain} from "../../__mocks__/mockedBeaconChain.js"; + +vi.mock("@lodestar/fork-choice"); describe("util / getShufflingDependentRoot", () => { - let forkchoiceStub: MockedBeaconChain["forkChoice"]; + let forkchoiceStub: Mocked; const headBattHeadBlock = { slot: 100, @@ -13,7 +14,7 @@ describe("util / getShufflingDependentRoot", () => { const blockEpoch = computeEpochAtSlot(headBattHeadBlock.slot); beforeEach(() => { - forkchoiceStub = getMockedBeaconChain().forkChoice; + forkchoiceStub = vi.mocked(new ForkChoice({} as any, {} as any, {} as any)); }); afterEach(() => { @@ -29,7 +30,7 @@ describe("util / getShufflingDependentRoot", () => { throw new Error("should not be called"); } }); - expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).to.be.equal("current"); + expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).toEqual("current"); }); it("should return next dependent root", () => { @@ -42,7 +43,7 @@ describe("util / getShufflingDependentRoot", () => { throw new Error("should not be called"); } }); - expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).to.be.equal("0x000"); + expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).toEqual("0x000"); }); it("should return head block root as dependent root", () => { @@ -51,7 +52,7 @@ describe("util / getShufflingDependentRoot", () => { forkchoiceStub.getDependentRoot.mockImplementation(() => { throw Error("should not be called"); }); - expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).to.be.equal( + expect(getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).toEqual( headBattHeadBlock.blockRoot ); }); @@ -62,6 +63,6 @@ describe("util / getShufflingDependentRoot", () => { forkchoiceStub.getDependentRoot.mockImplementation(() => { throw Error("should not be called"); }); - expect(() => getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).to.throw(); + expect(() => getShufflingDependentRoot(forkchoiceStub, attEpoch, blockEpoch, headBattHeadBlock)).toThrow(); }); }); diff --git a/packages/beacon-node/test/unit/util/kzg.test.ts b/packages/beacon-node/test/unit/util/kzg.test.ts index cfe35e8fc76e..e170aed1a2de 100644 --- a/packages/beacon-node/test/unit/util/kzg.test.ts +++ b/packages/beacon-node/test/unit/util/kzg.test.ts @@ -2,12 +2,12 @@ import {describe, it, expect, afterEach, beforeAll} from "vitest"; import {bellatrix, deneb, ssz} from "@lodestar/types"; import {BYTES_PER_FIELD_ELEMENT, BLOB_TX_TYPE} from "@lodestar/params"; import {createBeaconConfig, createChainForkConfig, defaultChainConfig} from "@lodestar/config"; +import {getMockedBeaconChain} from "../../mocks/mockedBeaconChain.js"; import {computeBlobSidecars, kzgCommitmentToVersionedHash} from "../../../src/util/blobs.js"; import {loadEthereumTrustedSetup, initCKZG, ckzg, FIELD_ELEMENTS_PER_BLOB_MAINNET} from "../../../src/util/kzg.js"; import {validateBlobSidecars, validateGossipBlobSidecar} from "../../../src/chain/validation/blobSidecar.js"; -import {getMockedBeaconChain} from "../../__mocks__/mockedBeaconChain.js"; -describe("C-KZG", async () => { +describe("C-KZG", () => { const afterEachCallbacks: (() => Promise | void)[] = []; afterEach(async () => { while (afterEachCallbacks.length > 0) { diff --git a/packages/beacon-node/test/utils/api.ts b/packages/beacon-node/test/utils/api.ts new file mode 100644 index 000000000000..41face1ae737 --- /dev/null +++ b/packages/beacon-node/test/utils/api.ts @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import {Mocked} from "vitest"; +import {config} from "@lodestar/config/default"; +import {ForkChoice} from "@lodestar/fork-choice"; +import {MockedBeaconChain, getMockedBeaconChain} from "../mocks/mockedBeaconChain.js"; +import {getMockedBeaconSync} from "../mocks/beaconSyncMock.js"; +import {MockedBeaconDb, getMockedBeaconDb} from "../mocks/mockedBeaconDb.js"; +import {getMockedNetwork} from "../mocks/mockedNetwork.js"; +import {ApiModules} from "../../src/api/index.js"; + +type ApiModulesWithoutConfig = Omit; + +export type ApiTestModules = {[K in keyof ApiModulesWithoutConfig]: Mocked} & { + chain: MockedBeaconChain; + forkChoice: Mocked; + db: MockedBeaconDb; + config: ApiModules["config"]; +}; + +export function getApiTestModules(): ApiTestModules { + const chainStub = getMockedBeaconChain(); + const syncStub = getMockedBeaconSync(); + const dbStub = getMockedBeaconDb(); + const networkStub = getMockedNetwork(); + + return { + config, + chain: chainStub, + sync: syncStub, + db: dbStub, + network: networkStub, + logger: chainStub.logger, + forkChoice: chainStub.forkChoice, + metrics: null, + }; +} diff --git a/packages/beacon-node/test/utils/logger.ts b/packages/beacon-node/test/utils/logger.ts index b3382cc221e2..1c1526514565 100644 --- a/packages/beacon-node/test/utils/logger.ts +++ b/packages/beacon-node/test/utils/logger.ts @@ -8,9 +8,9 @@ export type TestLoggerOpts = LoggerNodeOpts; /** * Run the test with ENVs to control log level: * ``` - * LOG_LEVEL=debug mocha .ts - * DEBUG=1 mocha .ts - * VERBOSE=1 mocha .ts + * LOG_LEVEL=debug vitest .ts + * DEBUG=1 vitest .ts + * VERBOSE=1 vitest .ts * ``` */ export const testLogger = (module?: string, opts?: TestLoggerOpts): LoggerNode => { diff --git a/packages/beacon-node/test/utils/mocks/chain.ts b/packages/beacon-node/test/utils/mocks/chain.ts deleted file mode 100644 index 9704b3a3f825..000000000000 --- a/packages/beacon-node/test/utils/mocks/chain.ts +++ /dev/null @@ -1,33 +0,0 @@ -import sinon from "sinon"; -import {IForkChoice, ProtoBlock, ExecutionStatus, ForkChoice} from "@lodestar/fork-choice"; -import {IBeaconChain, BeaconChain} from "../../../src/chain/index.js"; -import {ZERO_HASH_HEX} from "../../../src/constants/constants.js"; -import {StubbedChainMutable, StubbedOf} from "../stub/index.js"; -import {Mutable} from "../types.js"; - -export function getMockBeaconChain(): StubbedChainMutable { - return sinon.createStubInstance(BeaconChain) as StubbedChainMutable; -} - -export function getMockForkChoice(): StubbedOf> { - return sinon.createStubInstance(ForkChoice) as StubbedOf>; -} - -export const zeroProtoBlock: ProtoBlock = { - slot: 0, - blockRoot: ZERO_HASH_HEX, - parentRoot: ZERO_HASH_HEX, - stateRoot: ZERO_HASH_HEX, - targetRoot: ZERO_HASH_HEX, - - justifiedEpoch: 0, - justifiedRoot: ZERO_HASH_HEX, - finalizedEpoch: 0, - finalizedRoot: ZERO_HASH_HEX, - unrealizedJustifiedEpoch: 0, - unrealizedJustifiedRoot: ZERO_HASH_HEX, - unrealizedFinalizedEpoch: 0, - unrealizedFinalizedRoot: ZERO_HASH_HEX, - - ...{executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}, -}; diff --git a/packages/beacon-node/test/utils/mocks/db.ts b/packages/beacon-node/test/utils/mocks/db.ts deleted file mode 100644 index 16d7b32a1bcc..000000000000 --- a/packages/beacon-node/test/utils/mocks/db.ts +++ /dev/null @@ -1,72 +0,0 @@ -import {IBeaconDb} from "../../../src/db/index.js"; -import {CheckpointStateRepository} from "../../../src/db/repositories/checkpointState.js"; -import { - AttesterSlashingRepository, - BlockArchiveRepository, - BlockRepository, - DepositEventRepository, - DepositDataRootRepository, - Eth1DataRepository, - ProposerSlashingRepository, - StateArchiveRepository, - VoluntaryExitRepository, - BestLightClientUpdateRepository, - CheckpointHeaderRepository, - SyncCommitteeRepository, - SyncCommitteeWitnessRepository, - BackfilledRanges, - BlobSidecarsRepository, - BlobSidecarsArchiveRepository, - BLSToExecutionChangeRepository, -} from "../../../src/db/repositories/index.js"; -import {PreGenesisState, PreGenesisStateLastProcessedBlock} from "../../../src/db/single/index.js"; -import {createStubInstance} from "../types.js"; - -/* eslint-disable @typescript-eslint/no-empty-function */ - -/** - * Stubbed BeaconDb that ignores all DELETE and PUT actions, and returns void on all GET actions - */ -export function getStubbedBeaconDb(): IBeaconDb { - return { - // unfinalized blocks - block: createStubInstance(BlockRepository), - // finalized blocks - blockArchive: createStubInstance(BlockArchiveRepository), - - blobSidecars: createStubInstance(BlobSidecarsRepository), - blobSidecarsArchive: createStubInstance(BlobSidecarsArchiveRepository), - - // finalized states - stateArchive: createStubInstance(StateArchiveRepository), - checkpointState: createStubInstance(CheckpointStateRepository), - - // op pool - voluntaryExit: createStubInstance(VoluntaryExitRepository), - proposerSlashing: createStubInstance(ProposerSlashingRepository), - attesterSlashing: createStubInstance(AttesterSlashingRepository), - depositEvent: createStubInstance(DepositEventRepository), - blsToExecutionChange: createStubInstance(BLSToExecutionChangeRepository), - - // eth1 processing - preGenesisState: createStubInstance(PreGenesisState), - preGenesisStateLastProcessedBlock: createStubInstance(PreGenesisStateLastProcessedBlock), - - // all deposit data roots and merkle tree - depositDataRoot: createStubInstance(DepositDataRootRepository), - eth1Data: createStubInstance(Eth1DataRepository), - - // lightclient - bestLightClientUpdate: createStubInstance(BestLightClientUpdateRepository), - checkpointHeader: createStubInstance(CheckpointHeaderRepository), - syncCommittee: createStubInstance(SyncCommitteeRepository), - syncCommitteeWitness: createStubInstance(SyncCommitteeWitnessRepository), - - backfilledRanges: createStubInstance(BackfilledRanges), - - async close(): Promise {}, - /** To inject metrics after CLI initialization */ - setMetrics(): void {}, - async pruneHotDb(): Promise {}, - }; -} diff --git a/packages/beacon-node/test/utils/mocks/logger.ts b/packages/beacon-node/test/utils/mocks/logger.ts deleted file mode 100644 index d827805fa648..000000000000 --- a/packages/beacon-node/test/utils/mocks/logger.ts +++ /dev/null @@ -1,15 +0,0 @@ -import sinon, {SinonSandbox, SinonStubbedInstance} from "sinon"; -import {LoggerNode} from "@lodestar/logger/node"; - -export const createStubbedLogger = (sandbox?: SinonSandbox): LoggerNode & SinonStubbedInstance => { - sandbox = sandbox ?? sinon; - return { - debug: sandbox.stub(), - info: sandbox.stub(), - error: sandbox.stub(), - warn: sandbox.stub(), - verbose: sandbox.stub(), - child: sandbox.stub(), - toOpts: sandbox.stub(), - } as unknown as LoggerNode & SinonStubbedInstance; -}; diff --git a/packages/beacon-node/test/utils/network.ts b/packages/beacon-node/test/utils/network.ts index 5b0cdbe04b6c..56c831b269f5 100644 --- a/packages/beacon-node/test/utils/network.ts +++ b/packages/beacon-node/test/utils/network.ts @@ -1,30 +1,12 @@ +import {BitArray} from "@chainsafe/ssz"; import {PeerId} from "@libp2p/interface"; import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; -import {BitArray} from "@chainsafe/ssz"; import {ATTESTATION_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; -import {ssz} from "@lodestar/types"; -import {ChainForkConfig, createBeaconConfig} from "@lodestar/config"; -import { - GossipHandlers, - INetwork, - Network, - NetworkEvent, - NetworkInitModules, - getReqRespHandlers, -} from "../../src/network/index.js"; -import {createNodeJsLibp2p} from "../../src/network/libp2p/index.js"; +import {INetwork, Network, NetworkEvent} from "../../src/network/index.js"; import {Libp2p} from "../../src/network/interface.js"; -import {GetReqRespHandlerFn} from "../../src/network/reqresp/types.js"; -import {Eth1ForBlockProductionDisabled} from "../../src/eth1/index.js"; -import {defaultNetworkOptions, NetworkOptions} from "../../src/network/options.js"; -import {BeaconChain} from "../../src/chain/chain.js"; -import {ExecutionEngineDisabled} from "../../src/execution/index.js"; +import {createNodeJsLibp2p} from "../../src/network/libp2p/index.js"; +import {NetworkOptions, defaultNetworkOptions} from "../../src/network/options.js"; import {PeerIdStr} from "../../src/util/peerId.js"; -import {testLogger} from "./logger.js"; -import {generateState} from "./state.js"; -import {getStubbedBeaconDb} from "./mocks/db.js"; -import {ClockStatic} from "./clock.js"; -import {createCachedBeaconStateTest} from "./cachedBeaconState.js"; export async function createNode(multiaddr: string, inPeerId?: PeerId): Promise { const peerId = inPeerId || (await createSecp256k1PeerId()); @@ -42,101 +24,6 @@ export async function createNetworkModules( }; } -export type NetworkForTestOpts = { - startSlot?: number; - opts?: Partial; - gossipHandlersPartial?: Partial; - getReqRespHandler?: GetReqRespHandlerFn; -}; - -export async function getNetworkForTest( - loggerId: string, - config: ChainForkConfig, - opts: NetworkForTestOpts -): Promise<[network: Network, closeAll: () => Promise]> { - const logger = testLogger(loggerId); - const startSlot = opts.startSlot ?? 0; - - const block = ssz.phase0.SignedBeaconBlock.defaultValue(); - const state = generateState( - { - slot: startSlot, - finalizedCheckpoint: { - epoch: 0, - root: ssz.phase0.BeaconBlock.hashTreeRoot(block.message), - }, - }, - config - ); - - const beaconConfig = createBeaconConfig(config, state.genesisValidatorsRoot); - const db = getStubbedBeaconDb(); - - const chain = new BeaconChain( - { - safeSlotsToImportOptimistically: 0, - archiveStateEpochFrequency: 0, - suggestedFeeRecipient: "", - blsVerifyAllMainThread: true, - disableOnBlockError: true, - disableArchiveOnCheckpoint: true, - disableLightClientServerOnImportBlockHead: true, - disablePrepareNextSlot: true, - minSameMessageSignatureSetsToBatch: 32, - }, - { - config: beaconConfig, - db, - logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function - processShutdownCallback: () => {}, - // set genesis time so that we are at ALTAIR_FORK_EPOCH - // sinon mock timer does not work on worker thread - clock: new ClockStatic(startSlot, Math.floor(Date.now() / 1000) - startSlot * beaconConfig.SECONDS_PER_SLOT), - metrics: null, - anchorState: createCachedBeaconStateTest(state, beaconConfig), - eth1: new Eth1ForBlockProductionDisabled(), - executionEngine: new ExecutionEngineDisabled(), - } - ); - - const modules: Omit = { - config: beaconConfig, - chain, - db, - getReqRespHandler: opts.getReqRespHandler ?? getReqRespHandlers({db, chain}), - gossipHandlers: opts.gossipHandlersPartial as GossipHandlers, - metrics: null, - }; - - const network = await Network.init({ - ...modules, - peerId: await createSecp256k1PeerId(), - opts: { - ...defaultNetworkOptions, - maxPeers: 1, - targetPeers: 1, - bootMultiaddrs: [], - localMultiaddrs: ["/ip4/127.0.0.1/tcp/0"], - discv5FirstQueryDelayMs: 0, - discv5: null, - skipParamsLog: true, - // Disable rate limiting - rateLimitMultiplier: 0, - ...opts.opts, - }, - logger, - }); - - return [ - network, - async function closeAll() { - await network.close(); - await chain.close(); - }, - ]; -} - export async function getPeerIdOf(net: INetwork): Promise { return (await net.getNetworkIdentity()).peerId; } diff --git a/packages/beacon-node/test/utils/networkWithMockDb.ts b/packages/beacon-node/test/utils/networkWithMockDb.ts new file mode 100644 index 000000000000..3eea47892a0f --- /dev/null +++ b/packages/beacon-node/test/utils/networkWithMockDb.ts @@ -0,0 +1,109 @@ +import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {ChainForkConfig, createBeaconConfig} from "@lodestar/config"; +import {ssz} from "@lodestar/types"; +import {BeaconChain} from "../../src/chain/chain.js"; +import {Eth1ForBlockProductionDisabled} from "../../src/eth1/index.js"; +import {ExecutionEngineDisabled} from "../../src/execution/index.js"; +import {GossipHandlers, Network, NetworkInitModules, getReqRespHandlers} from "../../src/network/index.js"; +import {NetworkOptions, defaultNetworkOptions} from "../../src/network/options.js"; +import {GetReqRespHandlerFn} from "../../src/network/reqresp/types.js"; +import {getMockedBeaconDb} from "../mocks/mockedBeaconDb.js"; +import {createCachedBeaconStateTest} from "./cachedBeaconState.js"; +import {ClockStatic} from "./clock.js"; +import {testLogger} from "./logger.js"; +import {generateState} from "./state.js"; + +export type NetworkForTestOpts = { + startSlot?: number; + opts?: Partial; + gossipHandlersPartial?: Partial; + getReqRespHandler?: GetReqRespHandlerFn; +}; + +export async function getNetworkForTest( + loggerId: string, + config: ChainForkConfig, + opts: NetworkForTestOpts +): Promise<[network: Network, closeAll: () => Promise]> { + const logger = testLogger(loggerId); + const startSlot = opts.startSlot ?? 0; + + const block = ssz.phase0.SignedBeaconBlock.defaultValue(); + const state = generateState( + { + slot: startSlot, + finalizedCheckpoint: { + epoch: 0, + root: ssz.phase0.BeaconBlock.hashTreeRoot(block.message), + }, + }, + config + ); + + const beaconConfig = createBeaconConfig(config, state.genesisValidatorsRoot); + const db = getMockedBeaconDb(); + + const chain = new BeaconChain( + { + safeSlotsToImportOptimistically: 0, + archiveStateEpochFrequency: 0, + suggestedFeeRecipient: "", + blsVerifyAllMainThread: true, + disableOnBlockError: true, + disableArchiveOnCheckpoint: true, + disableLightClientServerOnImportBlockHead: true, + disablePrepareNextSlot: true, + minSameMessageSignatureSetsToBatch: 32, + }, + { + config: beaconConfig, + db, + logger, + // eslint-disable-next-line @typescript-eslint/no-empty-function + processShutdownCallback: () => {}, + // set genesis time so that we are at ALTAIR_FORK_EPOCH + // mock timer does not work on worker thread + clock: new ClockStatic(startSlot, Math.floor(Date.now() / 1000) - startSlot * beaconConfig.SECONDS_PER_SLOT), + metrics: null, + anchorState: createCachedBeaconStateTest(state, beaconConfig), + eth1: new Eth1ForBlockProductionDisabled(), + executionEngine: new ExecutionEngineDisabled(), + } + ); + + const modules: Omit = { + config: beaconConfig, + chain, + db, + getReqRespHandler: opts.getReqRespHandler ?? getReqRespHandlers({db, chain}), + gossipHandlers: opts.gossipHandlersPartial as GossipHandlers, + metrics: null, + }; + + const network = await Network.init({ + ...modules, + peerId: await createSecp256k1PeerId(), + opts: { + ...defaultNetworkOptions, + maxPeers: 1, + targetPeers: 1, + bootMultiaddrs: [], + localMultiaddrs: ["/ip4/127.0.0.1/tcp/0"], + discv5FirstQueryDelayMs: 0, + discv5: null, + skipParamsLog: true, + // Disable rate limiting + rateLimitMultiplier: 0, + ...opts.opts, + }, + logger, + }); + + return [ + network, + async function closeAll() { + await network.close(); + await chain.close(); + }, + ]; +} diff --git a/packages/beacon-node/test/utils/sinon/matcher.ts b/packages/beacon-node/test/utils/sinon/matcher.ts deleted file mode 100644 index 3fff4826579c..000000000000 --- a/packages/beacon-node/test/utils/sinon/matcher.ts +++ /dev/null @@ -1,8 +0,0 @@ -import sinon, {SinonMatcher} from "sinon"; -import {toHexString} from "@chainsafe/ssz"; - -export const bufferEqualsMatcher = (expected: Buffer): SinonMatcher => { - return sinon.match((value) => { - return toHexString(expected) === toHexString(value); - }); -}; diff --git a/packages/beacon-node/test/utils/state.ts b/packages/beacon-node/test/utils/state.ts index 64c223acf4ea..a0fa42be555e 100644 --- a/packages/beacon-node/test/utils/state.ts +++ b/packages/beacon-node/test/utils/state.ts @@ -12,6 +12,8 @@ import {allForks, altair, bellatrix, ssz} from "@lodestar/types"; import {createBeaconConfig, ChainForkConfig} from "@lodestar/config"; import {FAR_FUTURE_EPOCH, ForkName, ForkSeq, MAX_EFFECTIVE_BALANCE, SYNC_COMMITTEE_SIZE} from "@lodestar/params"; +import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice"; +import {ZERO_HASH_HEX} from "../../src/constants/constants.js"; import {generateValidator, generateValidators} from "./validator.js"; import {getConfig} from "./config.js"; @@ -134,3 +136,22 @@ export function generateCachedBellatrixState(opts?: TestBeaconState): CachedBeac index2pubkey: [], }); } + +export const zeroProtoBlock: ProtoBlock = { + slot: 0, + blockRoot: ZERO_HASH_HEX, + parentRoot: ZERO_HASH_HEX, + stateRoot: ZERO_HASH_HEX, + targetRoot: ZERO_HASH_HEX, + + justifiedEpoch: 0, + justifiedRoot: ZERO_HASH_HEX, + finalizedEpoch: 0, + finalizedRoot: ZERO_HASH_HEX, + unrealizedJustifiedEpoch: 0, + unrealizedJustifiedRoot: ZERO_HASH_HEX, + unrealizedFinalizedEpoch: 0, + unrealizedFinalizedRoot: ZERO_HASH_HEX, + + ...{executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}, +}; diff --git a/packages/beacon-node/test/utils/stub/index.ts b/packages/beacon-node/test/utils/stub/index.ts deleted file mode 100644 index a0eba06d0cf0..000000000000 --- a/packages/beacon-node/test/utils/stub/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {SinonStubbedInstance} from "sinon"; -import {IBeaconChain} from "../../../src/chain/index.js"; -import {Mutable} from "../types.js"; - -export type StubbedChain = IBeaconChain & SinonStubbedInstance; -export type StubbedOf = T & SinonStubbedInstance; - -/** Helper type to make dependencies mutable for validation tests */ -export type StubbedChainMutable = StubbedOf>; diff --git a/packages/beacon-node/test/utils/types.ts b/packages/beacon-node/test/utils/types.ts index a3d2f65bb892..1368c67282be 100644 --- a/packages/beacon-node/test/utils/types.ts +++ b/packages/beacon-node/test/utils/types.ts @@ -1,15 +1 @@ -import sinon from "sinon"; -import {SinonStub, SinonStubbedInstance} from "sinon"; - -export type SinonStubFn any> = T extends (...args: infer TArgs) => infer TReturnValue - ? SinonStub - : never; - -// eslint-disable-next-line @typescript-eslint/ban-types -type StubbableType = Function & {prototype: TType}; - -export function createStubInstance(constructor: StubbableType): SinonStubbedInstance & TType { - return sinon.createStubInstance(constructor) as SinonStubbedInstance & TType; -} - export type Mutable = Omit & {-readonly [key in K]: T[key]}; diff --git a/packages/beacon-node/vitest.config.e2e.ts b/packages/beacon-node/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/beacon-node/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/beacon-node/vitest.config.spec.ts b/packages/beacon-node/vitest.config.spec.ts index e5f588d17155..f4f301c7985f 100644 --- a/packages/beacon-node/vitest.config.spec.ts +++ b/packages/beacon-node/vitest.config.spec.ts @@ -1,19 +1,11 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.spec.config"; export default mergeConfig( vitestConfig, defineConfig({ test: { globalSetup: ["./test/globalSetup.ts"], - testTimeout: 60_000, - passWithNoTests: true, - pool: "threads", - poolOptions: { - threads: { - isolate: false, - }, - }, }, }) ); diff --git a/packages/beacon-node/vitest.config.ts b/packages/beacon-node/vitest.config.ts index 2a2b2c65304c..dbf15c3408f0 100644 --- a/packages/beacon-node/vitest.config.ts +++ b/packages/beacon-node/vitest.config.ts @@ -1,6 +1,6 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; import {buildTargetPlugin} from "../../scripts/vitest/plugins/buildTargetPlugin.js"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/cli/package.json b/packages/cli/package.json index 594ef5ebbb67..243dee688417 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -31,8 +31,8 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit/ --coverage", - "test:e2e": "vitest --run --poolOptions.threads.singleThread true --dir test/e2e/", + "test:unit": "vitest --run --dir test/unit/", + "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", "test:sim:multifork": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/multi_fork.test.ts", "test:sim:mixedclient": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/mixed_client.test.ts", "test:sim:endpoints": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/endpoints.test.ts", diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index 536e7ea24aa3..ea55b70e26c1 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; +import assert from "node:assert"; import {toHexString} from "@chainsafe/ssz"; -import {expect} from "chai"; import {ApiError, routes} from "@lodestar/api"; import {SimulationEnvironment} from "../utils/simulation/SimulationEnvironment.js"; import {BeaconClient, ExecutionClient} from "../utils/simulation/interfaces.js"; @@ -44,15 +44,15 @@ ApiError.assert(res); const stateValidators = res.response.data; await env.tracker.assert("should have correct validators count called without filters", async () => { - expect(stateValidators.length).to.be.equal(validatorCount); + assert.equal(stateValidators.length, validatorCount); }); await env.tracker.assert("should have correct validator index for first validator filters", async () => { - expect(stateValidators[0].index).to.be.equal(0); + assert.equal(stateValidators[0].index, 0); }); await env.tracker.assert("should have correct validator index for second validator filters", async () => { - expect(stateValidators[1].index).to.be.equal(1); + assert.equal(stateValidators[1].index, 1); }); await env.tracker.assert( @@ -66,7 +66,7 @@ await env.tracker.assert( }); ApiError.assert(res); - expect(res.response.data.length).to.be.equal(1); + assert.equal(res.response.data.length, 1); } ); @@ -81,7 +81,7 @@ await env.tracker.assert( }); ApiError.assert(res); - expect(toHexString(res.response.data[0].validator.pubkey)).to.be.equal(filterPubKey); + assert.equal(toHexString(res.response.data[0].validator.pubkey), filterPubKey); } ); @@ -93,7 +93,7 @@ await env.tracker.assert( const res = await node.api.beacon.getStateValidator("head", validatorIndex); ApiError.assert(res); - expect(res.response.data.index).to.be.equal(validatorIndex); + assert.equal(res.response.data.index, validatorIndex); } ); @@ -106,7 +106,7 @@ await env.tracker.assert( const res = await node.api.beacon.getStateValidator("head", hexPubKey); ApiError.assert(res); - expect(toHexString(res.response.data.validator.pubkey)).to.be.equal(hexPubKey); + assert.equal(toHexString(res.response.data.validator.pubkey), hexPubKey); } ); @@ -122,13 +122,13 @@ await env.tracker.assert("BN Not Synced", async () => { const res = await node.api.node.getSyncingStatus(); ApiError.assert(res); - expect(res.response.data).to.be.deep.equal(expectedSyncStatus); + assert.deepEqual(res.response.data, expectedSyncStatus); }); await env.tracker.assert("Return READY pre genesis", async () => { const {status} = await node.api.node.getHealth(); - expect(status).to.be.equal(routes.node.NodeHealth.READY); + assert.equal(status, routes.node.NodeHealth.READY); }); await env.stop(); diff --git a/packages/cli/test/utils.ts b/packages/cli/test/utils.ts index d4957240cbaf..81136c0a18d4 100644 --- a/packages/cli/test/utils.ts +++ b/packages/cli/test/utils.ts @@ -15,9 +15,9 @@ export type TestLoggerOpts = LoggerNodeOpts; /** * Run the test with ENVs to control log level: * ``` - * LOG_LEVEL=debug mocha .ts - * DEBUG=1 mocha .ts - * VERBOSE=1 mocha .ts + * LOG_LEVEL=debug vitest .ts + * DEBUG=1 vitest .ts + * VERBOSE=1 vitest .ts * ``` */ export const testLogger = (module?: string, opts?: TestLoggerOpts): LoggerNode => { diff --git a/packages/cli/vitest.config.e2e.ts b/packages/cli/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/cli/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/cli/vitest.config.ts +++ b/packages/cli/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/config/package.json b/packages/config/package.json index ed79bd700cfb..c52a070b69fd 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -50,7 +50,7 @@ "lint": "eslint --color --ext .ts src/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "yarn vitest --run --dir test/unit/ --coverage", + "test:unit": "yarn vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/config/vitest.config.ts b/packages/config/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/config/vitest.config.ts +++ b/packages/config/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/db/package.json b/packages/db/package.json index 13ffff098279..d99b21d80b9b 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -33,7 +33,7 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "dependencies": { diff --git a/packages/db/vitest.config.ts b/packages/db/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/db/vitest.config.ts +++ b/packages/db/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/flare/package.json b/packages/flare/package.json index d3849d1b5362..7417cf93c63d 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -44,7 +44,7 @@ "lint": "eslint --color --ext .ts src/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/flare/vitest.config.ts b/packages/flare/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/flare/vitest.config.ts +++ b/packages/flare/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index b19fa976bdf4..495c67a8e80b 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -34,7 +34,7 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "dependencies": { diff --git a/packages/fork-choice/test/unit/protoArray/computeDeltas.test.ts b/packages/fork-choice/test/unit/protoArray/computeDeltas.test.ts index 54b8a900d05c..fde551d43cda 100644 --- a/packages/fork-choice/test/unit/protoArray/computeDeltas.test.ts +++ b/packages/fork-choice/test/unit/protoArray/computeDeltas.test.ts @@ -132,52 +132,6 @@ describe("computeDeltas", () => { } }); - /** - * Starting Aug 2023, this test case is not valid because when an attestation is added - * to forkchoice, the block should come first, i.e. nextIndex should be a number - */ - // it("move out of tree", () => { - // const balance = 42; - - // const indices = new Map(); - // // there is only one block - // indices.set("2", 0); - - // // There are two validators - // const votes = [ - // // one validator moves their vote from the block to the zero hash - // { - // currentRoot: "2", - // nextRoot: "0", - // nextEpoch: 0, - // }, - // // one validator moves their vote from the block to something outside the tree - // { - // currentRoot: "2", - // nextRoot: "1337", - // nextEpoch: 0, - // }, - // ]; - - // const oldBalances = getEffectiveBalanceIncrementsZeroed(votes.length); - // const newBalances = getEffectiveBalanceIncrementsZeroed(votes.length); - // for (const balances of [oldBalances, newBalances]) { - // for (let i = 0; i < votes.length; i++) { - // balances[i] = balance; - // } - // } - - // const deltas = computeDeltas(indices, votes, oldBalances, newBalances, new Set()); - - // expect(deltas.length).to.eql(1); - - // expect(deltas[0].toString()).to.eql((0 - balance * 2).toString()); - - // for (const vote of votes) { - // expect(vote.currentRoot).to.equal(vote.nextRoot); - // } - // }); - it("changing balances", () => { const oldBalance = 42; const newBalance = 42 * 2; diff --git a/packages/fork-choice/vitest.config.ts b/packages/fork-choice/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/fork-choice/vitest.config.ts +++ b/packages/fork-choice/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/light-client/package.json b/packages/light-client/package.json index f34fe11601e8..dee231409730 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -59,7 +59,7 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit && yarn test:e2e", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/light-client/test/utils/utils.ts b/packages/light-client/test/utils/utils.ts index 455d6ef9997b..930cabfdad11 100644 --- a/packages/light-client/test/utils/utils.ts +++ b/packages/light-client/test/utils/utils.ts @@ -22,7 +22,7 @@ const CURRENT_SYNC_COMMITTEE_DEPTH = 5; /** * To enable debug logs run with * ``` - * DEBUG=true mocha ... + * DEBUG=true vitest ... * ``` */ export const testLogger = getLcLoggerConsole({logDebug: Boolean(process.env.DEBUG)}); diff --git a/packages/light-client/vitest.config.ts b/packages/light-client/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/light-client/vitest.config.ts +++ b/packages/light-client/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/logger/package.json b/packages/logger/package.json index e8cc7d5f9622..2f450ee5be12 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -56,12 +56,12 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e", "check-readme": "typescript-docs-verifier" }, "types": "lib/index.d.ts", diff --git a/packages/logger/test/unit/browser.test.ts b/packages/logger/test/unit/browser.test.ts index e2160418663a..591437450c2d 100644 --- a/packages/logger/test/unit/browser.test.ts +++ b/packages/logger/test/unit/browser.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect} from "vitest"; import {LogLevel} from "@lodestar/utils"; -import {stubLoggerForConsole} from "@lodestar/test-utils/mocha"; +import {stubLoggerForConsole} from "@lodestar/test-utils/doubles"; import {TimestampFormatCode, logFormats} from "../../src/index.js"; import {formatsTestCases} from "../fixtures/loggerFormats.js"; import {getBrowserLogger} from "../../src/browser.js"; diff --git a/packages/logger/test/unit/env.node.test.ts b/packages/logger/test/unit/env.node.test.ts index 4d2b914ca7f4..4bd4df689adf 100644 --- a/packages/logger/test/unit/env.node.test.ts +++ b/packages/logger/test/unit/env.node.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect} from "vitest"; import {LogLevel} from "@lodestar/utils"; -import {stubLoggerForConsole} from "@lodestar/test-utils/mocha"; +import {stubLoggerForConsole} from "@lodestar/test-utils/doubles"; import {TimestampFormatCode, logFormats} from "../../src/index.js"; import {formatsTestCases} from "../fixtures/loggerFormats.js"; import {getEnvLogger} from "../../src/env.js"; diff --git a/packages/logger/vitest.config.e2e.ts b/packages/logger/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/logger/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/logger/vitest.config.ts b/packages/logger/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/logger/vitest.config.ts +++ b/packages/logger/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/params/package.json b/packages/params/package.json index 7861da84424d..2586c73566aa 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -53,12 +53,12 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --dir test/e2e/", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/params/test/e2e/setPresetOk.ts b/packages/params/test/e2e/setPresetOk.ts index 8ab718337022..5e76149b293a 100644 --- a/packages/params/test/e2e/setPresetOk.ts +++ b/packages/params/test/e2e/setPresetOk.ts @@ -7,9 +7,9 @@ import {setActivePreset, PresetName} from "../../src/setPreset.js"; setActivePreset(PresetName.minimal); // 2. Import from any other @lodestar/params paths -import {expect} from "chai"; +import assert from "node:assert"; const {SLOTS_PER_EPOCH} = await import("../../src/index.js"); -expect(SLOTS_PER_EPOCH).to.equal(8, "SLOTS_PER_EPOCH should have minimal preset value"); -expect(process.env.LODESTAR_PRESET).to.equal(undefined, "LODESTAR_PRESET ENV must not be set"); +assert.equal(SLOTS_PER_EPOCH, 8, "SLOTS_PER_EPOCH should have minimal preset value"); +assert.equal(process.env.LODESTAR_PRESET, undefined, "LODESTAR_PRESET ENV must not be set"); diff --git a/packages/params/test/unit/activePreset.test.ts b/packages/params/test/unit/activePreset.test.ts index eceda7eaac92..3aeee69672a1 100644 --- a/packages/params/test/unit/activePreset.test.ts +++ b/packages/params/test/unit/activePreset.test.ts @@ -1,4 +1,4 @@ -import {describe, it, expect} from "vitest"; +import {describe, it, expect, beforeAll} from "vitest"; import {mainnetPreset} from "../../src/presets/mainnet.js"; import {minimalPreset} from "../../src/presets/minimal.js"; import {gnosisPreset as gnosisParams} from "../../src/presets/gnosis.js"; @@ -6,8 +6,13 @@ import {ACTIVE_PRESET, PresetName} from "../../src/index.js"; import {setActivePreset} from "../../src/setPreset.js"; import {setActivePreset as setActivePresetLib} from "../../src/setPreset.js"; -describe("active preset", async () => { - const exports = (await import("../../src/index.js")) as Record; +describe("active preset", () => { + let exports: Record; + + beforeAll(async () => { + exports = (await import("../../src/index.js")) as Record; + }); + const params = { [PresetName.mainnet]: mainnetPreset, [PresetName.minimal]: minimalPreset, @@ -30,8 +35,6 @@ describe("active preset", async () => { it("Should not allow to change preset", () => { expect(() => { - // I'm not sure if mocha is requiring from src or lib. Each file has different state. - // To ensure this throws, call setActivePreset on both the src and lib file. setActivePreset(PresetName.minimal); setActivePresetLib(PresetName.minimal); }).toThrow(); diff --git a/packages/params/test/unit/applicationDomains.test.ts b/packages/params/test/unit/applicationDomains.test.ts index 294ceb83ce44..f78e9aa22f07 100644 --- a/packages/params/test/unit/applicationDomains.test.ts +++ b/packages/params/test/unit/applicationDomains.test.ts @@ -8,7 +8,7 @@ describe("validate application domains", () => { for (let i = 0; i < DOMAIN_APPLICATION_MASK.length; i++) { r += DOMAIN_APPLICATION_MASK[i] & domain[i]; } - // eslint-disable-next-line chai-expect/no-inner-compare + expect(r > 0).toBeWithMessage(true, `${name} mask application should be valid`); }); }); diff --git a/packages/params/vitest.config.e2e.ts b/packages/params/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/params/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/params/vitest.config.ts b/packages/params/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/params/vitest.config.ts +++ b/packages/params/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/prover/package.json b/packages/prover/package.json index 80a992118202..05f7c33579b4 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -53,12 +53,12 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit && yarn test:e2e", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --poolOptions.threads.singleThread true --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e", "check-readme": "typescript-docs-verifier", "generate-fixtures": "node --loader ts-node/esm scripts/generate_fixtures.ts" }, diff --git a/packages/prover/test/unit/proof_provider/payload_store.test.ts b/packages/prover/test/unit/proof_provider/payload_store.test.ts index 02c9cc39f87f..738b6ef55f2a 100644 --- a/packages/prover/test/unit/proof_provider/payload_store.test.ts +++ b/packages/prover/test/unit/proof_provider/payload_store.test.ts @@ -67,13 +67,13 @@ describe("proof_provider/payload_store", function () { describe("finalized", () => { it("should return undefined for an empty store", () => { - expect(store.finalized).to.undefined; + expect(store.finalized).toBeUndefined(); }); it("should return undefined if no finalized block", () => { store.set(buildPayload({blockNumber: 10}), false); - expect(store.finalized).to.undefined; + expect(store.finalized).toBeUndefined(); }); it("should return finalized payload", () => { @@ -95,7 +95,7 @@ describe("proof_provider/payload_store", function () { describe("latest", () => { it("should return undefined for an empty store", () => { - expect(store.latest).to.undefined; + expect(store.latest).toBeUndefined(); }); it("should return latest payload if finalized", () => { @@ -260,8 +260,7 @@ describe("proof_provider/payload_store", function () { const executionPayload = (blockResponse.response?.data as capella.SignedBeaconBlock).message.body .executionPayload; api.beacon.getBlockV2.mockResolvedValue(blockResponse); - - expect(store.finalized).to.undefined; + expect(store.finalized).toBeUndefined(); // First process as unfinalized await store.processLCHeader(header, false); @@ -269,7 +268,7 @@ describe("proof_provider/payload_store", function () { await store.processLCHeader(header, true); // Called only once when we process unfinalized - expect(api.beacon.getBlockV2).to.be.toHaveBeenCalledOnce(); + expect(api.beacon.getBlockV2).toHaveBeenCalledOnce(); expect(store.finalized).toEqual(executionPayload); }); }); @@ -318,7 +317,7 @@ describe("proof_provider/payload_store", function () { describe("prune", () => { it("should prune without error for empty store", () => { - expect(() => store.prune()).not.to.throw; + expect(() => store.prune()).not.toThrow(); }); it("should prune the existing payloads if larger than MAX_PAYLOAD_HISTORY", () => { diff --git a/packages/prover/vitest.config.e2e.ts b/packages/prover/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/prover/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/prover/vitest.config.ts b/packages/prover/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/prover/vitest.config.ts +++ b/packages/prover/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 8cea3d0d6072..c19af565c397 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -50,7 +50,7 @@ "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", "test": "yarn test:unit", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "dependencies": { diff --git a/packages/reqresp/test/fixtures/encoders.ts b/packages/reqresp/test/fixtures/encoders.ts index 3024332a8bdd..408af282e2b1 100644 --- a/packages/reqresp/test/fixtures/encoders.ts +++ b/packages/reqresp/test/fixtures/encoders.ts @@ -187,7 +187,7 @@ export const responseEncodersTestCases: { skipEncoding: true, }, { - id: "Decode successfully response_chunk as a single concated chunk", + id: "Decode successfully response_chunk as a single concatenated chunk", protocol: pingNoHandler, responseChunks: [ {status: RespStatus.SUCCESS, payload: sszSnappyPing.binaryPayload}, diff --git a/packages/reqresp/test/unit/encoders/requestDecode.test.ts b/packages/reqresp/test/unit/encoders/requestDecode.test.ts index 60ccab1eecf1..462bc3bb7378 100644 --- a/packages/reqresp/test/unit/encoders/requestDecode.test.ts +++ b/packages/reqresp/test/unit/encoders/requestDecode.test.ts @@ -9,7 +9,7 @@ describe("encoders / requestDecode", () => { describe("valid cases", () => { it.each(requestEncodersCases)("$id", async ({protocol, requestBody, chunks}) => { const decodedBody = await pipe(arrToSource(chunks), requestDecode(protocol)); - expect(decodedBody).to.deep.equal(requestBody); + expect(decodedBody).toEqual(requestBody); }); }); diff --git a/packages/reqresp/test/unit/encoders/responseDecode.test.ts b/packages/reqresp/test/unit/encoders/responseDecode.test.ts index a6dfe092b169..6e73fbbba315 100644 --- a/packages/reqresp/test/unit/encoders/responseDecode.test.ts +++ b/packages/reqresp/test/unit/encoders/responseDecode.test.ts @@ -6,19 +6,22 @@ import {responseDecode} from "../../../src/encoders/responseDecode.js"; import {responseEncodersErrorTestCases, responseEncodersTestCases} from "../../fixtures/encoders.js"; import {expectRejectedWithLodestarError} from "../../utils/errors.js"; import {arrToSource, onlySuccessResp} from "../../utils/index.js"; +import {ResponseIncoming} from "../../../src/types.js"; describe("encoders / responseDecode", () => { describe("valid cases", () => { it.each(responseEncodersTestCases)("$id", async ({protocol, responseChunks, chunks}) => { - const responses = await pipe( + const responses = (await pipe( arrToSource(chunks), // eslint-disable-next-line @typescript-eslint/no-empty-function responseDecode(protocol, {onFirstHeader: () => {}, onFirstResponseChunk: () => {}}), all - ); + )) as ResponseIncoming[]; const expectedResponses = responseChunks.filter(onlySuccessResp).map((r) => r.payload); - expect(responses).to.deep.equal(expectedResponses); + expect(responses.map((r) => ({...r, data: Buffer.from(r.data)}))).toEqual( + expectedResponses.map((r) => ({...r, data: Buffer.from(r.data)})) + ); }); }); diff --git a/packages/reqresp/test/unit/rate_limiter/rateLimiterGRCA.test.ts b/packages/reqresp/test/unit/rate_limiter/rateLimiterGRCA.test.ts index b3393c609a76..a8cbb6e0d3a6 100644 --- a/packages/reqresp/test/unit/rate_limiter/rateLimiterGRCA.test.ts +++ b/packages/reqresp/test/unit/rate_limiter/rateLimiterGRCA.test.ts @@ -55,9 +55,4 @@ describe("rateLimiterGRCA", () => { expect(rateLimiter.allows(null, 10)).toBe(true); }); }); - - // This is a private behavior but important to test to avoid memory leaks - // describe("prune()", () => { - // it.skip("should remove old entries", () => {}); - // }); }); diff --git a/packages/reqresp/test/utils/errors.ts b/packages/reqresp/test/utils/errors.ts index c6cec8bc1392..16c098f2f57c 100644 --- a/packages/reqresp/test/utils/errors.ts +++ b/packages/reqresp/test/utils/errors.ts @@ -1,4 +1,4 @@ -import {expect} from "chai"; +import {expect} from "vitest"; import {LodestarError, mapValues} from "@lodestar/utils"; export function expectThrowsLodestarError(fn: () => void, expectedErr: LodestarError | string): void { @@ -36,7 +36,7 @@ export function expectLodestarErrorCode(err: LodestarE if (!(err instanceof LodestarError)) throw Error(`err not instanceof LodestarError: ${(err as Error).stack}`); const code = err.type.code; - expect(code).to.deep.equal(expectedCode, "Wrong LodestarError code"); + expect(code).toEqualWithMessage(expectedCode, "Wrong LodestarError code"); } export function expectLodestarError(err1: LodestarError, err2: LodestarError): void { @@ -47,7 +47,7 @@ export function expectLodestarError(err1: LodestarErro const errMeta1 = getErrorMetadata(err1); const errMeta2 = getErrorMetadata(err2); - expect(errMeta1).to.deep.equal(errMeta2, "Wrong LodestarError metadata"); + expect(errMeta1).toEqualWithMessage(errMeta2, "Wrong LodestarError metadata"); } export function getErrorMetadata(err: LodestarError | Error | unknown): unknown { diff --git a/packages/reqresp/test/utils/index.ts b/packages/reqresp/test/utils/index.ts index 98a7387233ba..c3c133352186 100644 --- a/packages/reqresp/test/utils/index.ts +++ b/packages/reqresp/test/utils/index.ts @@ -1,6 +1,6 @@ import {Direction, ReadStatus, Stream, StreamStatus, WriteStatus} from "@libp2p/interface"; import {logger} from "@libp2p/logger"; -import {expect} from "chai"; +import {expect} from "vitest"; import {Uint8ArrayList} from "uint8arraylist"; import {toHexString} from "@chainsafe/ssz"; import {fromHex} from "@lodestar/utils"; @@ -21,14 +21,24 @@ export async function* arrToSource(arr: T[]): AsyncGenerator { * Wrapper for type-safety to ensure and array of Buffers is equal with a diff in hex */ export function expectEqualByteChunks(chunks: Uint8Array[], expectedChunks: Uint8Array[], message?: string): void { - expect(chunks.map(toHexString).join("").replace(/0x/g, "")).to.deep.equal( - expectedChunks.map(toHexString).join("").replace(/0x/g, ""), - message - ); + if (message) { + expect(chunks.map(toHexString).join("").replace(/0x/g, "")).toEqualWithMessage( + expectedChunks.map(toHexString).join("").replace(/0x/g, ""), + message + ); + } else { + expect(chunks.map(toHexString).join("").replace(/0x/g, "")).toEqual( + expectedChunks.map(toHexString).join("").replace(/0x/g, "") + ); + } } export function expectInEqualByteChunks(chunks: Uint8Array[], expectedChunks: Uint8Array[], message?: string): void { - expect(chunks.map(toHexString)).not.to.deep.equal(expectedChunks.map(toHexString), message); + if (message) { + expect(chunks.map(toHexString)).not.toEqualWithMessage(expectedChunks.map(toHexString), message); + } else { + expect(chunks.map(toHexString)).not.toEqual(expectedChunks.map(toHexString)); + } } /** diff --git a/packages/reqresp/vitest.config.ts b/packages/reqresp/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/reqresp/vitest.config.ts +++ b/packages/reqresp/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/spec-test-util/README.md b/packages/spec-test-util/README.md index 7b9182a4729c..405a8b2ba51f 100644 --- a/packages/spec-test-util/README.md +++ b/packages/spec-test-util/README.md @@ -2,7 +2,7 @@ > This package is part of [ChainSafe's Lodestar](https://lodestar.chainsafe.io) project -Mocha / Chai utility for interacting with eth2.0 spec tests. +Vitest utility for interacting with eth2.0 spec tests. For usage see [spec tests]("https://github.com/ChainSafe/lodestar/tree/unstable/packages/beacon-node/test/spec") diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index ab427e2d0a41..899d6438d939 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -47,8 +47,8 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --passWithNoTests --dir test/unit/ --coverage", - "test:e2e": "vitest --run --dir test/e2e/", + "test:unit": "vitest --run --passWithNoTests --dir test/unit/", + "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" }, "repository": { @@ -65,7 +65,7 @@ "@lodestar/utils": "^1.14.0", "async-retry": "^1.3.3", "axios": "^1.3.4", - "vitest": "^1.1.0", + "vitest": "^1.2.1", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", "tar": "^6.1.13" @@ -75,6 +75,6 @@ "@types/tar": "^6.1.4" }, "peerDependencies": { - "vitest": "^1.1.0" + "vitest": "^1.2.1" } } diff --git a/packages/spec-test-util/test/e2e/single/index.test.ts b/packages/spec-test-util/test/e2e/single/index.test.ts index a20b783f4370..849b0cead30d 100644 --- a/packages/spec-test-util/test/e2e/single/index.test.ts +++ b/packages/spec-test-util/test/e2e/single/index.test.ts @@ -12,7 +12,6 @@ import {describeDirectorySpecTest, InputType, loadYamlFile} from "../../../src/s const __dirname = path.dirname(fileURLToPath(import.meta.url)); /* eslint-disable @typescript-eslint/naming-convention */ -/* eslint-disable mocha/no-exports, mocha/no-top-level-hooks */ export type SimpleStruct = { test: boolean; diff --git a/packages/spec-test-util/vitest.config.e2e.ts b/packages/spec-test-util/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/spec-test-util/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/spec-test-util/vitest.config.ts b/packages/spec-test-util/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/spec-test-util/vitest.config.ts +++ b/packages/spec-test-util/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index 2b49b94179ca..cbde9b062177 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -52,7 +52,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, "types": "lib/index.d.ts", diff --git a/packages/state-transition/test/perf/sanityCheck.test.ts b/packages/state-transition/test/perf/sanityCheck.test.ts index 83f48be749d4..834e118d0f76 100644 --- a/packages/state-transition/test/perf/sanityCheck.test.ts +++ b/packages/state-transition/test/perf/sanityCheck.test.ts @@ -32,8 +32,6 @@ describe("Perf test sanity check", function () { const phase0State = generatePerfTestCachedStatePhase0(); const cache = beforeProcessEpoch(phase0State); expect( - // Chai does not support bigint comparisons - // eslint-disable-next-line chai-expect/no-inner-compare BigInt(cache.prevEpochUnslashedStake.targetStakeByIncrement) * BigInt(EFFECTIVE_BALANCE_INCREMENT) > targetStake, `targetStake too low: ${ BigInt(cache.prevEpochUnslashedStake.targetStakeByIncrement) * BigInt(EFFECTIVE_BALANCE_INCREMENT) diff --git a/packages/state-transition/test/utils/beforeValue.ts b/packages/state-transition/test/utils/beforeValue.ts index 61ae3daa32a1..f50520372e17 100644 --- a/packages/state-transition/test/utils/beforeValue.ts +++ b/packages/state-transition/test/utils/beforeValue.ts @@ -3,7 +3,7 @@ import {beforeAll} from "vitest"; export type LazyValue = {value: T}; /** - * Register a callback to compute a value in the before() block of mocha tests + * Register a callback to compute a value in the before() block of vitest tests * ```ts * const state = beforeValue(() => getState()) * it("test", () => { diff --git a/packages/state-transition/test/utils/types.ts b/packages/state-transition/test/utils/types.ts deleted file mode 100644 index a3a28f1cca32..000000000000 --- a/packages/state-transition/test/utils/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {SinonStub} from "sinon"; - -export type SinonStubFn any> = T extends (...args: infer TArgs) => infer TReturnValue - ? SinonStub - : never; diff --git a/packages/state-transition/vitest.config.ts b/packages/state-transition/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/state-transition/vitest.config.ts +++ b/packages/state-transition/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/test-utils/.mocharc.yaml b/packages/test-utils/.mocharc.yaml deleted file mode 100644 index 1f15bf5929e0..000000000000 --- a/packages/test-utils/.mocharc.yaml +++ /dev/null @@ -1,4 +0,0 @@ -colors: true -extension: ["ts"] -node-option: - - "loader=ts-node/esm" diff --git a/packages/test-utils/.nycrc.json b/packages/test-utils/.nycrc.json deleted file mode 100644 index 69aa626339a0..000000000000 --- a/packages/test-utils/.nycrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../.nycrc.json" -} diff --git a/packages/test-utils/README.md b/packages/test-utils/README.md index cc7db46c0990..105e0ca7950f 100644 --- a/packages/test-utils/README.md +++ b/packages/test-utils/README.md @@ -2,7 +2,7 @@ > This package is part of [ChainSafe's Lodestar](https://lodestar.chainsafe.io) project -Mocha / Chai and other utility to reuse across testing of other packages. +Vitest and other utility to reuse across testing of other packages. For usage see [spec tests]("https://github.com/ChainSafe/lodestar/tree/unstable/packages/beacon-node/test/spec") diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 61914ba91676..d4a1df589e8f 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -14,11 +14,8 @@ ".": { "import": "./lib/index.js" }, - "./sinon": { - "import": "./lib/sinon.js" - }, - "./mocha": { - "import": "./lib/mocha.js" + "./doubles": { + "import": "./lib/doubles.js" } }, "typesVersions": { @@ -66,20 +63,16 @@ "@lodestar/params": "^1.14.0", "@lodestar/utils": "^1.14.0", "axios": "^1.3.4", - "chai": "^4.3.7", - "mocha": "^10.2.0", - "sinon": "^15.0.3", "testcontainers": "^10.2.1", - "tmp": "^0.2.1" + "tmp": "^0.2.1", + "vitest": "^1.2.1" }, "devDependencies": { "@types/dockerode": "^3.3.19", - "@types/mocha": "^10.0.1", "@types/yargs": "^17.0.24", "yargs": "^17.7.1" }, "peerDependencies": { - "chai": "^4.3.7", - "mocha": "^10.2.0" + "vitest": "^1.2.1" } } diff --git a/packages/test-utils/src/mocha.ts b/packages/test-utils/src/doubles.ts similarity index 55% rename from packages/test-utils/src/mocha.ts rename to packages/test-utils/src/doubles.ts index 7b8c10ad5342..c61c10ea6099 100644 --- a/packages/test-utils/src/mocha.ts +++ b/packages/test-utils/src/doubles.ts @@ -1,48 +1,26 @@ -import type {Suite} from "mocha"; +import {vi, MockInstance} from "vitest"; import {Logger} from "@lodestar/utils"; -import {TestContext} from "./interfaces.js"; -export type {TestContext} from "./interfaces.js"; + +type Callback = () => void; +type Handler = (cb: Callback) => void; /** - * Create a Mocha context object that can be used to register callbacks that will be executed + * Stub the logger methods */ -export function getMochaContext(suite: Suite): TestContext { - const afterEachCallbacks: (() => Promise | void)[] = []; - const beforeEachCallbacks: (() => Promise | void)[] = []; - const afterAllCallbacks: (() => Promise | void)[] = []; - - const context: TestContext = { - afterEach: (cb) => afterEachCallbacks.push(cb), - beforeEach: (cb) => beforeEachCallbacks.push(cb), - afterAll: (cb) => afterAllCallbacks.push(cb), - }; - - const callbacks = [afterEachCallbacks, beforeEachCallbacks, afterAllCallbacks]; - const hooks = [suite.afterEach, suite.beforeEach, suite.afterAll]; - - for (const [index, cbs] of callbacks.entries()) { - const hook = hooks[index].bind(suite); - - hook(async function mochaHook() { - // Add increased timeout for that hook - this.timeout(10000); - - const errs: Error[] = []; - for (const cb of cbs) { - try { - await cb(); - } catch (e) { - errs.push(e as Error); - } - } - cbs.length = 0; // Reset array - if (errs.length > 0) { - throw errs[0]; - } - }); - } +export function stubLogger(context: {beforeEach: Handler; afterEach: Handler}, logger = console): void { + context.beforeEach(() => { + vi.spyOn(logger, "info"); + vi.spyOn(logger, "log"); + vi.spyOn(logger, "warn"); + vi.spyOn(logger, "error"); + }); - return context; + context.afterEach(() => { + (logger.info as unknown as MockInstance).mockRestore(); + (logger.log as unknown as MockInstance).mockRestore(); + (logger.warn as unknown as MockInstance).mockRestore(); + (logger.error as unknown as MockInstance).mockRestore(); + }); } // Typescript does not support array of generics so have to use this flexible workaround diff --git a/packages/test-utils/src/sinon.ts b/packages/test-utils/src/sinon.ts deleted file mode 100644 index 9c75dd171248..000000000000 --- a/packages/test-utils/src/sinon.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {SinonSpy, spy} from "sinon"; - -type Callback = () => void; -type Handler = (cb: Callback) => void; - -/** - * Stub the logger methods - */ -export function stubLogger(context: {beforeEach: Handler; afterEach: Handler}, logger = console): void { - context.beforeEach(() => { - spy(logger, "info"); - spy(logger, "log"); - spy(logger, "warn"); - spy(logger, "error"); - }); - - context.afterEach(() => { - (logger.info as SinonSpy).restore(); - (logger.log as SinonSpy).restore(); - (logger.warn as SinonSpy).restore(); - (logger.error as SinonSpy).restore(); - }); -} diff --git a/packages/types/package.json b/packages/types/package.json index 9d8859ecaf05..b51acbef6801 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -61,9 +61,9 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "test:constants:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/constants/ --coverage", - "test:constants:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/constants/ --coverage", - "test:unit": "wrapper() { yarn test:constants:minimal $@ && yarn test:constants:mainnet $@ && vitest --run --dir test/unit/ --coverage $@; }; wrapper", + "test:constants:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/constants/", + "test:constants:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/constants/", + "test:unit": "wrapper() { yarn test:constants:minimal $@ && yarn test:constants:mainnet $@ && vitest --run --dir test/unit/ $@; }; wrapper", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/types/test/constants/blobs.test.ts b/packages/types/test/constants/blobs.test.ts index 93193463e76b..4b145161d292 100644 --- a/packages/types/test/constants/blobs.test.ts +++ b/packages/types/test/constants/blobs.test.ts @@ -19,7 +19,7 @@ describe(`${constants.ACTIVE_PRESET}/ blobs pre-computed constants`, () => { for (const [key, expectedValue] of Object.entries(correctConstants)) { it(key, () => { - expect((constants as unknown as Record)[key]).to.equal(expectedValue); + expect((constants as unknown as Record)[key]).toEqual(expectedValue); }); } }); diff --git a/packages/types/vitest.config.ts b/packages/types/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/types/vitest.config.ts +++ b/packages/types/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/utils/package.json b/packages/utils/package.json index 9f526582483e..fcc0f5ac36c1 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -31,7 +31,7 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit/ --coverage", + "test:unit": "vitest --run --dir test/unit", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/utils/test/unit/err.test.ts b/packages/utils/test/unit/err.test.ts index a4b30ee65d73..54908c50ccd3 100644 --- a/packages/utils/test/unit/err.test.ts +++ b/packages/utils/test/unit/err.test.ts @@ -1,6 +1,5 @@ import {describe, it, expect} from "vitest"; import {Err, isErr, mapOkResults, mapOkResultsAsync, Result} from "../../src/err.js"; -import {expectDeepEquals, expectEquals} from "../utils/chai.js"; /* eslint-disable @typescript-eslint/no-unsafe-assignment */ @@ -28,21 +27,18 @@ describe("Result Err", () => { for (const [i, value] of values.entries()) { it(`${i} Ok(${String(value)})`, () => { // Any value must not be detected as error - expectEquals(isErr(value), false); + expect(isErr(value)).toBeFalsy(); }); it(`${i} Err(${String(value)})`, () => { // Any value can be wrapped in Err - expectEquals(isErr(Err(value)), true); + expect(isErr(Err(value))).toBeTruthy(); }); } }); describe("mapOkResults", () => { it("empty case", () => { - expectDeepEquals( - mapOkResults([], () => []), - [] - ); + expect(mapOkResults([], () => [])).toEqual([]); }); it("throw for different length", () => { @@ -54,13 +50,13 @@ describe("Result Err", () => { const results1 = mapOkResults(results0, (resultsOk) => resultsOk.map((num) => (num >= 5 ? Err(num) : String(num))) ); - expectDeepEquals(results1, ["0", Err(1), "2", Err(3), "4", Err(5), Err(6), Err(7)]); + expect(results1).toEqual(["0", Err(1), "2", Err(3), "4", Err(5), Err(6), Err(7)]); }); }); describe("mapOkResultsAsync", () => { it("empty case", async () => { - expectDeepEquals(await mapOkResultsAsync([], async () => []), []); + expect(await mapOkResultsAsync([], async () => [])).toEqual([]); }); it("reject for different length", async () => { @@ -77,7 +73,7 @@ describe("Result Err", () => { const results1 = await mapOkResultsAsync(results0, async (resultsOk) => resultsOk.map((num) => (num >= 5 ? Err(num) : String(num))) ); - expectDeepEquals(results1, ["0", Err(1), "2", Err(3), "4", Err(5), Err(6), Err(7)]); + expect(results1).toEqual(["0", Err(1), "2", Err(3), "4", Err(5), Err(6), Err(7)]); }); }); }); diff --git a/packages/utils/test/utils/chai.ts b/packages/utils/test/utils/chai.ts deleted file mode 100644 index 3c1e855021be..000000000000 --- a/packages/utils/test/utils/chai.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {expect} from "chai"; - -export function expectDeepEquals(a: T, b: T, message?: string): void { - expect(a).deep.equals(b, message); -} - -export function expectEquals(a: T, b: T, message?: string): void { - expect(a).equals(b, message); -} diff --git a/packages/utils/vitest.config.ts b/packages/utils/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/utils/vitest.config.ts +++ b/packages/utils/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/validator/package.json b/packages/validator/package.json index 14ee1002b214..92c3e92d04a1 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -28,10 +28,10 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "pretest": "yarn run check-types", - "test:unit": "vitest --run --dir test/unit --coverage", + "test:unit": "vitest --run --dir test/unit/", "test": "yarn test:unit", "test:spec": "vitest --run --config vitest.config.spec.ts --dir test/spec/", - "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --poolOptions.threads.singleThread true --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.config.e2e.ts --dir test/e2e", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", "coverage": "codecov -F lodestar-validator", "check-readme": "typescript-docs-verifier" diff --git a/packages/validator/test/e2e/web3signer.test.ts b/packages/validator/test/e2e/web3signer.test.ts index c93f1786dfb4..326dbae8c4f7 100644 --- a/packages/validator/test/e2e/web3signer.test.ts +++ b/packages/validator/test/e2e/web3signer.test.ts @@ -137,7 +137,6 @@ describe("web3signer signature test", function () { // ValidatorRegistration includes a timestamp so it's possible that web3signer instance and local instance // sign different messages and this test fails. Disabling unless it can be proven deterministic - // eslint-disable-next-line mocha/no-skipped-tests it.skip("signValidatorRegistration", async () => { const regAttributes = { feeRecipient: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", diff --git a/packages/validator/test/setup.ts b/packages/validator/test/setup.ts deleted file mode 100644 index b83e6cb78511..000000000000 --- a/packages/validator/test/setup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import sinonChai from "sinon-chai"; - -chai.use(chaiAsPromised); -chai.use(sinonChai); diff --git a/packages/validator/test/unit/services/attestation.test.ts b/packages/validator/test/unit/services/attestation.test.ts index c8010fe1bdf0..64948ec92529 100644 --- a/packages/validator/test/unit/services/attestation.test.ts +++ b/packages/validator/test/unit/services/attestation.test.ts @@ -1,5 +1,4 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach, vi} from "vitest"; -import sinon from "sinon"; import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; import {ssz} from "@lodestar/types"; @@ -98,10 +97,9 @@ describe("AttestationService", function () { }); // Mock duties service to return some duties directly - attestationService["dutiesService"].getDutiesAtSlot = sinon.stub().returns(duties); + vi.spyOn(attestationService["dutiesService"], "getDutiesAtSlot").mockImplementation(() => duties); // Mock beacon's attestation and aggregates endpoints - api.validator.produceAttestationData.mockResolvedValue({ response: {data: attestation.data}, ok: true, diff --git a/packages/validator/test/unit/services/syncCommittee.test.ts b/packages/validator/test/unit/services/syncCommittee.test.ts index 20697f651ca9..922447ddf85f 100644 --- a/packages/validator/test/unit/services/syncCommittee.test.ts +++ b/packages/validator/test/unit/services/syncCommittee.test.ts @@ -109,7 +109,7 @@ describe("SyncCommitteeService", function () { }); // Mock duties service to return some duties directly - syncCommitteeService["dutiesService"].getDutiesAtSlot = vi.fn().mockReturnValue(duties); + vi.spyOn(syncCommitteeService["dutiesService"], "getDutiesAtSlot").mockResolvedValue(duties); // Mock beacon's sync committee and contribution routes diff --git a/packages/validator/test/unit/utils/clock.test.ts b/packages/validator/test/unit/utils/clock.test.ts index 8bb12e6ef8ae..15f95ddbe2ee 100644 --- a/packages/validator/test/unit/utils/clock.test.ts +++ b/packages/validator/test/unit/utils/clock.test.ts @@ -89,12 +89,11 @@ describe("util / Clock", function () { {name: "should return next slot after 12s", delta: 12}, {name: "should return next slot after 12.5s", delta: 12.5}, ]; - for (const {name, delta} of testCase) { - it(name, async function () { - const currentSlot = getCurrentSlotAround(testConfig, genesisTime); - vi.advanceTimersByTime(delta * 1000); - expect(getCurrentSlotAround(testConfig, genesisTime)).toBe(currentSlot + 1); - }); - } + + it.each(testCase)("$name", async function ({delta}) { + const currentSlot = getCurrentSlotAround(testConfig, genesisTime); + vi.advanceTimersByTime(delta * 1000); + expect(getCurrentSlotAround(testConfig, genesisTime)).toBe(currentSlot + 1); + }); }); }); diff --git a/packages/validator/test/utils/logger.ts b/packages/validator/test/utils/logger.ts index 6077b23a9583..8eaed6dfe6c1 100644 --- a/packages/validator/test/utils/logger.ts +++ b/packages/validator/test/utils/logger.ts @@ -5,9 +5,9 @@ import {ClockMock} from "./clock.js"; /** * Run the test with ENVs to control log level: * ``` - * LOG_LEVEL=debug mocha .ts - * DEBUG=1 mocha .ts - * VERBOSE=1 mocha .ts + * LOG_LEVEL=debug vitest .ts + * DEBUG=1 vitest .ts + * VERBOSE=1 vitest .ts * ``` */ export const testLogger = getEnvLogger; diff --git a/packages/validator/vitest.config.e2e.ts b/packages/validator/vitest.config.e2e.ts new file mode 100644 index 000000000000..b9f913705ef2 --- /dev/null +++ b/packages/validator/vitest.config.e2e.ts @@ -0,0 +1,11 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "../../vitest.base.e2e.config"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + globalSetup: ["./test/globalSetup.ts"], + }, + }) +); diff --git a/packages/validator/vitest.config.spec.ts b/packages/validator/vitest.config.spec.ts index e5f588d17155..a207c8e29675 100644 --- a/packages/validator/vitest.config.spec.ts +++ b/packages/validator/vitest.config.spec.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/packages/validator/vitest.config.ts b/packages/validator/vitest.config.ts index 1df0de848936..7a6069341168 100644 --- a/packages/validator/vitest.config.ts +++ b/packages/validator/vitest.config.ts @@ -1,5 +1,5 @@ import {defineConfig, mergeConfig} from "vitest/config"; -import vitestConfig from "../../vitest.base.config"; +import vitestConfig from "../../vitest.base.unit.config"; export default mergeConfig( vitestConfig, diff --git a/tsconfig.build.json b/tsconfig.build.json index d767c8eaec8a..8034a32ce679 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -25,10 +25,8 @@ "incremental": true, "preserveWatchOutput": true, - - // There are two duplicate type definitions included from `chai` and `vitest` packages. - // There is one invalid type declaration introduced from `webdriverio -> got` package. - // TODO: Once we completely remove `chai` and upgrade `webdriverio` we can enable this check again. + // TODO: Investigate following errors: + // - Cannot find module 'rollup/parseAst' or its corresponding type declarations "skipLibCheck": true, } } diff --git a/vitest.base.e2e.config.ts b/vitest.base.e2e.config.ts new file mode 100644 index 000000000000..b8b19c124bad --- /dev/null +++ b/vitest.base.e2e.config.ts @@ -0,0 +1,19 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "./vitest.base.unit.config.js"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + coverage: { + enabled: false, + }, + pool: "forks", + poolOptions: { + forks: { + singleFork: true, + }, + }, + }, + }) +); diff --git a/vitest.base.spec.config.ts b/vitest.base.spec.config.ts new file mode 100644 index 000000000000..72125edcfa81 --- /dev/null +++ b/vitest.base.spec.config.ts @@ -0,0 +1,22 @@ +import {defineConfig, mergeConfig} from "vitest/config"; +import vitestConfig from "./vitest.base.unit.config.js"; + +export default mergeConfig( + vitestConfig, + defineConfig({ + test: { + coverage: { + enabled: false, + }, + testTimeout: 60_000, + hookTimeout: 60_000, + passWithNoTests: true, + pool: "threads", + poolOptions: { + threads: { + isolate: false, + }, + }, + }, + }) +); diff --git a/vitest.base.config.ts b/vitest.base.unit.config.ts similarity index 96% rename from vitest.base.config.ts rename to vitest.base.unit.config.ts index 2c12cbf41b9b..b087466fec12 100644 --- a/vitest.base.config.ts +++ b/vitest.base.unit.config.ts @@ -17,6 +17,7 @@ export default defineConfig({ setupFiles: [path.join(__dirname, "./scripts/vitest/customMatchers.ts")], reporters: ["default", "hanging-process"], coverage: { + enabled: process.env.CI === "true", clean: true, all: false, extension: [".ts"], diff --git a/webpack.test.config.js b/webpack.test.config.js deleted file mode 100644 index 0949c76886d4..000000000000 --- a/webpack.test.config.js +++ /dev/null @@ -1,66 +0,0 @@ -const webpack = require("webpack"); -const ResolveTypeScriptPlugin = require("resolve-typescript-plugin"); - -module.exports = { - mode: "production", - target: "web", - experiments: { - topLevelAwait: true, - }, - optimization: { - minimize: false, - }, - stats: { - errors: true, - errorDetails: true, - }, - plugins: [ - new webpack.ProvidePlugin({ - process: "process/browser.js", - // eslint-disable-next-line @typescript-eslint/naming-convention - Buffer: ["buffer", "Buffer"], - }), - ], - module: { - exprContextCritical: false, - rules: [ - { - test: /\.ts?$/, - use: [ - { - loader: "ts-loader", - options: { - configFile: "tsconfig.e2e.json", - experimentalFileCaching: true, - transpileOnly: true, - projectReferences: true, - }, - }, - ], - exclude: [/node_modules/], - }, - ], - }, - resolve: { - plugins: [new ResolveTypeScriptPlugin({includeNodeModules: false})], - fallback: { - path: require.resolve("path-browserify"), - "node:path": require.resolve("path-browserify"), - http: require.resolve("stream-http"), - https: require.resolve("https-browserify"), - stream: require.resolve("stream-browserify"), - "node:stream": require.resolve("stream-browserify"), - "@chainsafe/blst": false, - process: false, - fs: false, - os: false, - zlib: false, - crypto: false, - url: false, - }, - alias: { - process: "process/browser.js", - }, - extensions: [".ts", ".js"], - }, -}; diff --git a/yarn.lock b/yarn.lock index a6621b6fbd0c..c39d68175f13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -203,163 +203,11 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/code-frame@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/core@^7.7.5": - version "7.11.4" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz" - integrity sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.4" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.4": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz" - integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== - dependencies: - "@babel/types" "^7.15.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@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== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - 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.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== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@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== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-member-expression-to-functions@^7.10.4": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz" - integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-module-transforms@^7.11.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz" - integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/template" "^7.10.4" - "@babel/types" "^7.11.0" - lodash "^4.17.19" - -"@babel/helper-optimise-call-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== - dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== - "@babel/helper-string-parser@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== -"@babel/helper-validator-identifier@^7.10.4": - version "7.14.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== - "@babel/helper-validator-identifier@^7.18.6": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" @@ -370,29 +218,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== - -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== - dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - chalk "^2.0.0" - js-tokens "^4.0.0" - "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -402,74 +227,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.10.4", "@babel/parser@^7.11.4": - version "7.15.3" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz" - integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== - -"@babel/parser@^7.22.15", "@babel/parser@^7.23.6": +"@babel/parser@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== -"@babel/parser@^7.23.3": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.5.tgz#37dee97c4752af148e1d38c34b856b2507660563" - integrity sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ== - -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.15.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" - integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== - dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - to-fast-properties "^2.0.0" - -"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6": +"@babel/types@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== @@ -478,15 +241,6 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.23.3": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.5.tgz#48d730a00c95109fa4393352705954d74fb5b602" - integrity sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - "@balena/dockerignore@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" @@ -1537,18 +1291,7 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": +"@istanbuljs/schema@^0.1.2": version "0.1.3" resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== @@ -1560,7 +1303,7 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.0": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== @@ -1584,11 +1327,6 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/source-map@^0.3.3": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.4.tgz#856a142864530d4059dda415659b48d37db2d556" - integrity sha512-KE/SxsDqNs3rrWwFHcRh15ZLVFrI0YoZtgAdIyIq9k5hUNmiWRXXThPomIxHuL20sLdgzbDFyvkUMna14bvtrw== - "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" @@ -1607,7 +1345,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17": +"@jridgewell/trace-mapping@^0.3.12": version "0.3.18" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== @@ -2644,7 +2382,7 @@ picocolors "^1.0.0" tslib "^2.6.0" -"@polka/url@^1.0.0-next.20": +"@polka/url@^1.0.0-next.24": version "1.0.0-next.24" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3" integrity sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ== @@ -2907,48 +2645,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== -"@sinonjs/commons@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" - integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== - dependencies: - type-detect "4.0.8" - -"@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz#d10549ed1f423d80639c528b6c7f5a1017747d0c" - integrity sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw== - dependencies: - "@sinonjs/commons" "^2.0.0" - -"@sinonjs/fake-timers@^10.3.0": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@sinonjs/samsam@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" - integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== - dependencies: - "@sinonjs/commons" "^2.0.0" - lodash.get "^4.4.2" - type-detect "^4.0.8" - -"@sinonjs/text-encoding@^0.7.1": - version "0.7.1" - resolved "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz" - integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== - "@swc/core-darwin-arm64@1.3.101": version "1.3.101" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.101.tgz#9ffdc0e77c31b20877fa7405c82905e0c76738d0" @@ -3119,43 +2815,11 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/chai-as-promised@^7.1.6": - version "7.1.6" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz#3b08cbe1e7206567a480dc6538bade374b19e4e1" - integrity sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA== - dependencies: - "@types/chai" "*" - -"@types/chai@*": - version "4.2.17" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.2.17.tgz" - integrity sha512-LaiwWNnYuL8xJlQcE91QB2JoswWZckq9A4b+nMPq8dt8AP96727Nb3X4e74u+E3tm4NLTILNI9MYFsyVc30wSA== - -"@types/chai@^4.3.6": - version "4.3.6" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.6.tgz#7b489e8baf393d5dd1266fb203ddd4ea941259e6" - integrity sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw== - -"@types/component-emitter@^1.2.10": - version "1.2.11" - resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" - integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== - -"@types/cookie@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" - integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== - "@types/cookiejar@*": version "2.1.2" resolved "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz" integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== -"@types/cors@^2.8.12": - version "2.8.12" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" - integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== - "@types/datastore-level@^3.0.0": version "3.0.0" resolved "https://registry.npmjs.org/@types/datastore-level/-/datastore-level-3.0.0.tgz" @@ -3193,27 +2857,6 @@ "@types/docker-modem" "*" "@types/node" "*" -"@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.5.tgz#acdfb7dd36b91cc5d812d7c093811a8f3d9b31e4" - integrity sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - "@types/estree@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" @@ -3273,11 +2916,6 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== -"@types/json-schema@*", "@types/json-schema@^7.0.8": - 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== - "@types/json-schema@^7.0.12": version "7.0.13" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" @@ -3342,10 +2980,10 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/mocha@^10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" - integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== +"@types/mocha@^10.0.6": + version "10.0.6" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.6.tgz#818551d39113081048bdddbef96701b4e8bb9d1b" + integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== "@types/mockery@^1.4.30": version "1.4.30" @@ -3373,7 +3011,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.7.0", "@types/node@^20.6.5": +"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20.6.5": version "20.6.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.5.tgz#4c6a79adf59a8e8193ac87a0e522605b16587258" integrity sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w== @@ -3435,28 +3073,6 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564" integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw== -"@types/sinon-chai@^3.2.9": - version "3.2.9" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" - integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*": - version "10.0.13" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" - integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinon@^10.0.16": - version "10.0.16" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.16.tgz#4bf10313bd9aa8eef1e50ec9f4decd3dd455b4d3" - integrity sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - "@types/sinon@^17.0.0": version "17.0.2" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.2.tgz#9a769f67e62b45b7233f1fe01cb1f231d2393e1c" @@ -3617,6 +3233,14 @@ "@typescript-eslint/visitor-keys" "6.7.2" debug "^4.3.4" +"@typescript-eslint/scope-manager@6.19.0": + version "6.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz#b6d2abb825b29ab70cb542d220e40c61c1678116" + integrity sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ== + dependencies: + "@typescript-eslint/types" "6.19.0" + "@typescript-eslint/visitor-keys" "6.19.0" + "@typescript-eslint/scope-manager@6.7.2": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz#cf59a2095d2f894770c94be489648ad1c78dc689" @@ -3635,11 +3259,30 @@ debug "^4.3.4" ts-api-utils "^1.0.1" +"@typescript-eslint/types@6.19.0": + version "6.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.0.tgz#689b0498c436272a6a2059b09f44bcbd90de294a" + integrity sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A== + "@typescript-eslint/types@6.7.2": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.2.tgz#75a615a6dbeca09cafd102fe7f465da1d8a3c066" integrity sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg== +"@typescript-eslint/typescript-estree@6.19.0": + version "6.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz#0813ba364a409afb4d62348aec0202600cb468fa" + integrity sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ== + dependencies: + "@typescript-eslint/types" "6.19.0" + "@typescript-eslint/visitor-keys" "6.19.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + "@typescript-eslint/typescript-estree@6.7.2": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz#ce5883c23b581a5caf878af641e49dd0349238c7" @@ -3666,6 +3309,27 @@ "@typescript-eslint/typescript-estree" "6.7.2" semver "^7.5.4" +"@typescript-eslint/utils@^6.15.0": + version "6.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.0.tgz#557b72c3eeb4f73bef8037c85dae57b21beb1a4b" + integrity sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.19.0" + "@typescript-eslint/types" "6.19.0" + "@typescript-eslint/typescript-estree" "6.19.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.19.0": + version "6.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz#4565e0ecd63ca1f81b96f1dd76e49f746c6b2b49" + integrity sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ== + dependencies: + "@typescript-eslint/types" "6.19.0" + eslint-visitor-keys "^3.4.1" + "@typescript-eslint/visitor-keys@6.7.2": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz#4cb2bd786f1f459731b0ad1584c9f73e1c7a4d5c" @@ -3674,19 +3338,19 @@ "@typescript-eslint/types" "6.7.2" eslint-visitor-keys "^3.4.1" -"@vitest/browser@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/browser/-/browser-1.1.0.tgz#b3c3e06d04506309a1e163103e1f65ee1391c262" - integrity sha512-59Uwoiw/zAQPmqgIKrzev8HNfeNlD8Q/nDyP9Xqg1D3kaM0tcOT/wk5RnZFW5f0JdguK0c1+vSeOPUSrOja1hQ== +"@vitest/browser@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/browser/-/browser-1.2.1.tgz#ad04b261416b211804199df0a717c9ecddf5f006" + integrity sha512-jhaQ15zWYAwz8anXgmLW0yAVLCXdT8RFv7LeW9bg7sMlvGJaTCTIHaHWFvCdADF/i62+22tnrzgiiqSnApjXtA== dependencies: - estree-walker "^3.0.3" + "@vitest/utils" "1.2.1" magic-string "^0.30.5" - sirv "^2.0.3" + sirv "^2.0.4" -"@vitest/coverage-v8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.1.0.tgz#bc0bbb99fcb608f72794701a86302ff3aabbc125" - integrity sha512-kHQRk70vTdXAyQY2C0vKOHPyQD/R6IUzcGdO4vCuyr4alE5Yg1+Sk2jSdjlIrTTXdcNEs+ReWVM09mmSFJpzyQ== +"@vitest/coverage-v8@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.2.1.tgz#e76d64c8f0a8cb882543f12f7a2bc7615b84cbee" + integrity sha512-fJEhKaDwGMZtJUX7BRcGxooGwg1Hl0qt53mVup/ZJeznhvL5EodteVnb/mcByhEcvVWbK83ZF31c7nPEDi4LOQ== dependencies: "@ampproject/remapping" "^2.2.1" "@bcoe/v8-coverage" "^0.2.3" @@ -3696,72 +3360,73 @@ istanbul-lib-source-maps "^4.0.1" istanbul-reports "^3.1.6" magic-string "^0.30.5" - magicast "^0.3.2" + magicast "^0.3.3" picocolors "^1.0.0" std-env "^3.5.0" test-exclude "^6.0.0" v8-to-istanbul "^9.2.0" -"@vitest/expect@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.1.0.tgz#f58eef7de090ad65f30bb93ec54fa9f94c9d1d5d" - integrity sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w== +"@vitest/expect@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.2.1.tgz#574c0ac138a9e34522da202ea4c48a3adfe7240e" + integrity sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ== dependencies: - "@vitest/spy" "1.1.0" - "@vitest/utils" "1.1.0" + "@vitest/spy" "1.2.1" + "@vitest/utils" "1.2.1" chai "^4.3.10" -"@vitest/runner@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.1.0.tgz#b3bf60f4a78f4324ca09811dd0f87b721a96b534" - integrity sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw== +"@vitest/runner@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.2.1.tgz#13e65b47eb04e572b99757e55f063f8f025822b2" + integrity sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ== dependencies: - "@vitest/utils" "1.1.0" + "@vitest/utils" "1.2.1" p-limit "^5.0.0" pathe "^1.1.1" -"@vitest/snapshot@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.1.0.tgz#b9924e4303382b43bb2c31061b173e69a6fb3437" - integrity sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ== +"@vitest/snapshot@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.2.1.tgz#bd2dcae2322b90bab1660421ff9dae73fc84ecc0" + integrity sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q== dependencies: magic-string "^0.30.5" pathe "^1.1.1" pretty-format "^29.7.0" -"@vitest/spy@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.1.0.tgz#7f40697e4fc217ac8c3cc89a865d1751b263f561" - integrity sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg== +"@vitest/spy@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.2.1.tgz#2777444890de9d32e55e600e34a13b2074cabc18" + integrity sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ== dependencies: tinyspy "^2.2.0" -"@vitest/utils@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.1.0.tgz#d177a5f41bdb484bbb43c8d73a77ca782df068b5" - integrity sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ== +"@vitest/utils@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.2.1.tgz#ad798cb13ec9e9e97b13be65d135e9e8e3c586aa" + integrity sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg== dependencies: diff-sequences "^29.6.3" + estree-walker "^3.0.3" loupe "^2.3.7" pretty-format "^29.7.0" -"@wdio/config@8.27.0": - version "8.27.0" - resolved "https://registry.yarnpkg.com/@wdio/config/-/config-8.27.0.tgz#c738d8108b5161cf3f80bb34d0e1f4d700b1a9ce" - integrity sha512-zYM5daeiBVVAbQj0ASymAt0RUsocLVIwKiUHNa8gg/1GsZnztGjetXExSp1gXlxtMVM5xWUSKjh6ceFK79gWDQ== +"@wdio/config@8.28.0": + version "8.28.0" + resolved "https://registry.yarnpkg.com/@wdio/config/-/config-8.28.0.tgz#7b6928aa90d432cff35555b039dbae449b6e8235" + integrity sha512-uXav11uUZSqbYyXGLzyggO8togdm6Bjdjkg8f0zZe4nQpqKpLAkcH7jRiekhuj7oIV5hZai6w5YFhFy5nsw/QA== dependencies: - "@wdio/logger" "8.24.12" - "@wdio/types" "8.27.0" - "@wdio/utils" "8.27.0" + "@wdio/logger" "8.28.0" + "@wdio/types" "8.28.0" + "@wdio/utils" "8.28.0" decamelize "^6.0.0" deepmerge-ts "^5.0.0" glob "^10.2.2" import-meta-resolve "^4.0.0" -"@wdio/logger@8.24.12": - version "8.24.12" - resolved "https://registry.yarnpkg.com/@wdio/logger/-/logger-8.24.12.tgz#03cb8bb7ce7ee443e1dcd200a3b44270ae16a1f9" - integrity sha512-QisOiVIWKTUCf1H7S+DOtC+gruhlpimQrUXfWMTeeh672PvAJYnTpOJDWA+BtXfsikkUYFAzAaq8SeMJk8rqKg== +"@wdio/logger@8.28.0": + version "8.28.0" + resolved "https://registry.yarnpkg.com/@wdio/logger/-/logger-8.28.0.tgz#ab97ee1a9f6a30305e1a07ff2b67fa23e1281e73" + integrity sha512-/s6zNCqwy1hoc+K4SJypis0Ud0dlJ+urOelJFO1x0G0rwDRWyFiUP6ijTaCcFxAm29jYEcEPWijl2xkVIHwOyA== dependencies: chalk "^5.1.2" loglevel "^1.6.0" @@ -3790,21 +3455,21 @@ dependencies: "@types/node" "^20.1.0" -"@wdio/types@8.27.0": - version "8.27.0" - resolved "https://registry.yarnpkg.com/@wdio/types/-/types-8.27.0.tgz#ef2e3a9ae083f08ee5fe5bf9e5dfc70cc55cebcb" - integrity sha512-LbP9FKh8r0uW9/dKhTIUCC1Su8PsP9TmzGKXkWt6/IMacgJiB/zW3u1CgyaLw9lG0UiQORHGoeJX9zB2HZAh4w== +"@wdio/types@8.28.0": + version "8.28.0" + resolved "https://registry.yarnpkg.com/@wdio/types/-/types-8.28.0.tgz#9dd5189699b2b636db2fb2b6f205d6417b876053" + integrity sha512-4/mUn3IGNa1GTiV0PMOtl1sRqStpbHOQldxz4Vheh0lYNc15W12jXRm84CwGsV6UW93GO9W2K9EprFJsUjc9sg== dependencies: "@types/node" "^20.1.0" -"@wdio/utils@8.27.0": - version "8.27.0" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-8.27.0.tgz#6cb9b29649b4e301a959a8e8aea831edec635d55" - integrity sha512-4BY+JBQssVn003P5lA289uDMie3LtGinHze5btkcW9timB6VaU+EeZS4eKTPC0pziizLhteVvXYxv3YTpeeRfA== +"@wdio/utils@8.28.0": + version "8.28.0" + resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-8.28.0.tgz#df71392b0382b7e3ca62d24d3bf333ce83911038" + integrity sha512-v3xDJuQShLSfHW/Ee0y3z9ZtiV/UrILlucgKBCwCpLwHnO5HhfAH4Ehirt0yzQvYz+Pn9BuOXJImD/wsSbJtLw== dependencies: "@puppeteer/browsers" "^1.6.0" - "@wdio/logger" "8.24.12" - "@wdio/types" "8.27.0" + "@wdio/logger" "8.28.0" + "@wdio/types" "8.28.0" decamelize "^6.0.0" deepmerge-ts "^5.1.0" edgedriver "^5.3.5" @@ -3816,137 +3481,6 @@ split2 "^4.2.0" wait-port "^1.0.4" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - -"@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== - -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== - -"@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-opt" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - "@webassemblyjs/wast-printer" "1.11.6" - -"@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== - dependencies: - "@webassemblyjs/ast" "1.11.6" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -4025,19 +3559,6 @@ abstract-logging@^2.0.1: resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== -accepts@~1.3.4: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -4048,26 +3569,21 @@ acorn-walk@^8.1.1: resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn-walk@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.0.tgz#2097665af50fd0cf7a2dfccd2b9368964e66540f" - integrity sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA== +acorn-walk@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== acorn@^8.10.0, acorn@^8.9.0: version "8.10.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== -acorn@^8.4.1, acorn@^8.7.1: +acorn@^8.4.1: version "8.7.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== -acorn@^8.8.2: - version "8.9.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" - integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== - add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -4121,12 +3637,7 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -4232,13 +3743,6 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -append-transform@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz" - integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== - dependencies: - default-require-extensions "^3.0.0" - "aproba@^1.0.3 || ^2.0.0": version "2.0.0" resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" @@ -4497,7 +4001,7 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" -async@^3.2.3, async@~3.2.2: +async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== @@ -4585,11 +4089,6 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0, base64id@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" - integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== - base64url@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz" @@ -4732,24 +4231,6 @@ bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@^1.19.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" - integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.10.3" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - boolean@^3.0.1: version "3.2.0" resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" @@ -4872,16 +4353,6 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.14.5: - version "4.21.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" - integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA== - dependencies: - caniuse-lite "^1.0.30001366" - electron-to-chromium "^1.4.188" - node-releases "^2.0.6" - update-browserslist-db "^1.0.4" - buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -4984,11 +4455,6 @@ byte-size@8.1.1: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.1.tgz#3424608c62d59de5bfda05d31e0313c6174842ae" integrity sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg== -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - c-kzg@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/c-kzg/-/c-kzg-2.1.2.tgz#355eca750c1b70398f533be5dd33e7ffbde005d8" @@ -4997,24 +4463,6 @@ c-kzg@^2.1.2: bindings "^1.5.0" node-addon-api "^5.0.0" -c8@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/c8/-/c8-8.0.1.tgz#bafd60be680e66c5530ee69f621e45b1364af9fd" - integrity sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@istanbuljs/schema" "^0.1.3" - find-up "^5.0.0" - foreground-child "^2.0.0" - istanbul-lib-coverage "^3.2.0" - istanbul-lib-report "^3.0.1" - istanbul-reports "^3.1.6" - rimraf "^3.0.2" - test-exclude "^6.0.0" - v8-to-istanbul "^9.0.0" - yargs "^17.7.2" - yargs-parser "^21.1.1" - cac@^6.7.14: version "6.7.14" resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" @@ -5123,16 +4571,6 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -caching-transform@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz" - integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== - dependencies: - hasha "^5.0.0" - make-dir "^3.0.0" - package-hash "^4.0.0" - write-file-atomic "^3.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -5155,7 +4593,7 @@ camelcase-keys@^6.2.2: map-obj "^4.0.0" quick-lru "^4.0.1" -camelcase@^5.0.0, camelcase@^5.3.1: +camelcase@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -5165,11 +4603,6 @@ camelcase@^6.0.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001366: - version "1.0.30001370" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz#0a30d4f20d38b9e108cc5ae7cc62df9fe66cd5ba" - integrity sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g== - case@^1.6.3: version "1.6.3" resolved "https://registry.npmjs.org/case/-/case-1.6.3.tgz" @@ -5180,14 +4613,7 @@ catering@^2.0.0, catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -chai-as-promised@^7.1.1: - version "7.1.1" - resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== - dependencies: - check-error "^1.0.2" - -chai@^4.3.10, chai@^4.3.7, chai@^4.3.8: +chai@^4.3.10: version "4.3.10" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== @@ -5215,7 +4641,7 @@ chalk@4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -5255,11 +4681,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - check-error@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" @@ -5267,7 +4688,7 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -chokidar@3.5.3, chokidar@^3.5.1: +chokidar@3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -5292,11 +4713,6 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - chromium-bidi@0.4.16: version "0.4.16" resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.16.tgz#8a67bfdf6bb8804efc22765a82859d20724b46ab" @@ -5372,15 +4788,6 @@ cli-width@^4.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.0.0.tgz#a5622f6a3b0a9e3e711a25f099bf2399f608caf6" integrity sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw== -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -5481,11 +4888,6 @@ color@3.0.x: color-convert "^1.9.1" color-string "^1.5.2" -colors@1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - colorspace@1.1.x: version "1.1.2" resolved "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz" @@ -5502,16 +4904,6 @@ columnify@1.6.0: strip-ansi "^6.0.1" wcwidth "^1.0.0" -combine-source-map@~0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" - integrity sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg== - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" - combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -5519,35 +4911,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -commander@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/commander/-/commander-1.0.4.tgz#5edeb1aee23c4fb541a6b70d692abef19669a2d3" - integrity sha512-Xz0JOF7NqSubDnWmw7qvX1FuIpCsV62ci/gkpa2NFlm+roeMniBtbxK8QePjs762ZGsuhKaGgcb83eaBiSJ16A== - dependencies: - keypress "0.1.x" - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@^9.3.0: version "9.5.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== -commander@~2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A== - dependencies: - graceful-readlink ">= 1.0.0" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -5561,7 +4929,7 @@ compare-module-exports@^2.1.0: resolved "https://registry.npmjs.org/compare-module-exports/-/compare-module-exports-2.1.0.tgz" integrity sha512-3Lc0sTIuX1jmY2K2RrXRJOND6KsRTX2D4v3+eu1PDptsuJZVK4LZc852eZa9I+avj0NrUKlTNgqvccNOH6mbGg== -component-emitter@^1.3.0, component-emitter@~1.3.0: +component-emitter@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -5601,16 +4969,6 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" -connect@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz" @@ -5633,11 +4991,6 @@ content-disposition@^0.5.3: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - conventional-changelog-angular@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz#a9a9494c28b7165889144fd5b91573c4aa9ca541" @@ -5711,43 +5064,16 @@ conventional-recommended-bump@7.0.1: git-semver-tags "^5.0.0" meow "^8.1.2" -convert-source-map@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" - integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== - -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -convert-source-map@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" - integrity sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg== - -convert-source-map@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.2.0.tgz#44c08c2506f10fb3ca6fd888d5a3444cf8d6a669" - integrity sha512-S8g9WfpATYd4Qajgygr9CsIRSvd+omrKmaqLE0Lz4dSWprOFpWSqYTrXBTNrYqM+x4OaLlFWhJSOJHU8vuU1wA== - cookie@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - cookiejar@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" @@ -5763,14 +5089,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@~2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - cosmiconfig@^8.2.0: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" @@ -5924,11 +5242,6 @@ csv-stringify@^5.6.2: resolved "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.2.tgz" integrity sha512-n3rIVbX6ylm1YsX2NEug9IaPV8xRnT+9/NNZbrA/bcHgOSSeqtWla6XnI/xmyu57wIw+ASCAoX1oM6EZtqJV0A== -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== - dargs@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" @@ -5984,23 +5297,11 @@ datastore-level@*, datastore-level@^10.1.1: it-take "^3.0.1" level "^8.0.0" -date-format@^4.0.11, date-format@^4.0.13: - version "4.0.13" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.13.tgz#87c3aab3a4f6f37582c5f5f63692d2956fa67890" - integrity sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ== - dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" @@ -6008,7 +5309,7 @@ debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1: dependencies: ms "2.1.2" -debug@4.3.4, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4.3.4, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -6030,7 +5331,7 @@ decamelize-keys@^1.1.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.2.0: +decamelize@^1.1.0: version "1.2.0" resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -6102,13 +5403,6 @@ default-browser@^4.0.0: execa "^7.1.1" titleize "^3.0.0" -default-require-extensions@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz" - integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== - dependencies: - strip-bom "^4.0.0" - defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -6209,11 +5503,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" @@ -6229,10 +5518,10 @@ devtools-protocol@0.0.1147663: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1147663.tgz#4ec5610b39a6250d1f87e6b9c7e16688ed0ac78e" integrity sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ== -devtools-protocol@^0.0.1237913: - version "0.0.1237913" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1237913.tgz#ac0208ff0cbe9c53646753576b5c1d788e3caa38" - integrity sha512-Pxtmz2ZIqBkpU82HaIdsvCQBG94yTC4xajrEsWx9p38QKEfBCJktSazsHkrjf9j3dVVNPhg5LR21F6KWeXpjiQ== +devtools-protocol@^0.0.1245094: + version "0.0.1245094" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1245094.tgz#fc84014e144730edb59c0591a6629600b570e54f" + integrity sha512-c7Tk8wCk2bw+wuQbl8vDh/7rDboWY8TEtcuHj5Q8S9E4F0AJMGJBnp+OqBCTI+xuVeGitQHt04/Rp3tzUStJxg== dezalgo@^1.0.4: version "1.0.4" @@ -6242,11 +5531,6 @@ dezalgo@^1.0.4: asap "^2.0.0" wrappy "1" -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== - diff-sequences@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" @@ -6262,11 +5546,6 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" @@ -6340,16 +5619,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-serialize@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^2.0.0" - domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz" @@ -6414,11 +5683,6 @@ edgedriver@^5.3.5: unzipper "^0.10.14" which "^4.0.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - ejs@^3.1.7: version "3.1.9" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" @@ -6426,11 +5690,6 @@ ejs@^3.1.7: dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.188: - version "1.4.200" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.200.tgz#6e4c5266106688965b4ea7caa11f0dd315586854" - integrity sha512-nPyI7oHc8T64oSqRXrAt99gNMpk0SAgPHw/o+hkNKyb5+bcdnFtZcSO9FUJES5cVkVZvo8u4qiZ1gQILl8UXsA== - electron@^26.2.2: version "26.2.4" resolved "https://registry.yarnpkg.com/electron/-/electron-26.2.4.tgz#36616b2386b083c13ae9188f2d8ccf233c23404a" @@ -6468,11 +5727,6 @@ enabled@2.0.x: resolved "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - encoding@^0.1.12, encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -6487,36 +5741,7 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -engine.io-parser@~5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0" - integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== - -engine.io@~6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0" - integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== - dependencies: - "@types/cookie" "^0.4.1" - "@types/cors" "^2.8.12" - "@types/node" ">=10.0.0" - accepts "~1.3.4" - base64id "2.0.0" - cookie "~0.4.1" - cors "~2.8.5" - debug "~4.3.1" - engine.io-parser "~5.0.3" - ws "~8.2.3" - -enhanced-resolve@^5.0.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enhanced-resolve@^5.12.0, enhanced-resolve@^5.15.0: +enhanced-resolve@^5.12.0: version "5.15.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== @@ -6531,11 +5756,6 @@ enquirer@~2.3.6: dependencies: ansi-colors "^4.1.1" -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== - entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" @@ -6734,11 +5954,6 @@ es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.11" -es-module-lexer@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" - integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== - es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -6764,7 +5979,7 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es6-error@^4.0.1, es6-error@^4.1.1: +es6-error@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== @@ -6874,11 +6089,6 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-chai-expect@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-chai-expect/-/eslint-plugin-chai-expect-3.0.0.tgz#812d7384756177b2d424040cb3c20e78606db1b2" - integrity sha512-NS0YBcToJl+BRKBSMCwRs/oHJIX67fG5Gvb4tGked+9Wnd1/PzKijd82B2QVKcSSOwRe+pp4RAJ2AULeck4eQw== - eslint-plugin-es@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz" @@ -6910,14 +6120,6 @@ eslint-plugin-import@^2.28.1: semver "^6.3.1" tsconfig-paths "^3.14.2" -eslint-plugin-mocha@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-10.2.0.tgz#15b05ce5be4b332bb0d76826ec1c5ebf67102ad6" - integrity sha512-ZhdxzSZnd1P9LqDPF0DBcFLpRIGdh1zkF2JHnQklKQOvrQtT73kdP5K9V2mzvbLR+cCAO9OI48NXK/Ax9/ciCQ== - dependencies: - eslint-utils "^3.0.0" - rambda "^7.4.0" - eslint-plugin-prettier@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz#6887780ed95f7708340ec79acfdf60c35b9be57a" @@ -6926,13 +6128,12 @@ eslint-plugin-prettier@^5.0.0: prettier-linter-helpers "^1.0.0" synckit "^0.8.5" -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== +eslint-plugin-vitest@^0.3.20: + version "0.3.20" + resolved "https://registry.yarnpkg.com/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.20.tgz#9c4e02dd0252ad359b1e02dbcfbe4cf7ad8d091a" + integrity sha512-O05k4j9TGMOkkghj9dRgpeLDyOSiVIxQWgNDPfhYPm5ioJsehcYV/zkRLekQs+c8+RBCVXucSED3fYOyy2EoWA== dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" + "@typescript-eslint/utils" "^6.15.0" eslint-scope@^7.2.2: version "7.2.2" @@ -6949,23 +6150,11 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - eslint-visitor-keys@^1.1.0: version "1.3.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== - eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" @@ -7066,11 +6255,6 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" @@ -7182,7 +6366,7 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== -events@^3.0.0, events@^3.2.0, events@^3.3.0: +events@^3.0.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -7272,11 +6456,6 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -7520,28 +6699,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^3.2.0: - version "3.3.1" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-my-way@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-7.6.0.tgz#f1e271fd1aafe87e87860662f9940124274f73c7" @@ -7600,11 +6757,6 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -flatted@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" - integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== - fn.name@1.x.x: version "1.1.0" resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz" @@ -7627,14 +6779,6 @@ foreach@^2.0.5: resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= -foreground-child@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz" - integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^3.0.2" - foreground-child@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" @@ -7697,11 +6841,6 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fromentries@^1.2.0: - version "1.3.2" - resolved "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz" - integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== - fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" @@ -7870,12 +7009,7 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" -gensync@^1.0.0-beta.1: - version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -7938,11 +7072,6 @@ get-iterator@^2.0.1: resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-2.0.1.tgz#a904829f61bace789e0d64bd1a504c511a015c3f" integrity sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg== -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - get-pkg-repo@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385" @@ -8071,11 +7200,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - glob@7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" @@ -8111,7 +7235,7 @@ glob@^10.2.2: 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.7: +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== @@ -8177,11 +7301,6 @@ global-agent@^3.0.0: semver "^7.3.2" serialize-error "^7.0.1" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.19.0: version "13.20.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" @@ -8254,7 +7373,7 @@ graceful-fs@4.2.11, graceful-fs@^4.2.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -8264,11 +7383,6 @@ graceful-fs@^4.2.6: resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w== - grapheme-splitter@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" @@ -8364,14 +7478,6 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hasha@^5.0.0: - version "5.2.2" - resolved "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz" - integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== - dependencies: - is-stream "^2.0.0" - type-fest "^0.8.0" - hasown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" @@ -8553,13 +7659,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - iconv-lite@0.6.3, iconv-lite@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -8567,6 +7666,13 @@ iconv-lite@0.6.3, iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@1.1.13: version "1.1.13" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz" @@ -8690,13 +7796,6 @@ init-package-json@5.0.0: validate-npm-package-license "^3.0.4" validate-npm-package-name "^5.0.0" -inline-source-map@~0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" - integrity sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA== - dependencies: - source-map "~0.5.3" - inquirer@^8.2.4: version "8.2.4" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4" @@ -8885,13 +7984,6 @@ is-core-module@^2.13.0: dependencies: has "^1.0.3" -is-core-module@^2.2.0, is-core-module@^2.5.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - is-core-module@^2.3.0: version "2.5.0" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz" @@ -8899,6 +7991,13 @@ is-core-module@^2.3.0: dependencies: has "^1.0.3" +is-core-module@^2.5.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + dependencies: + has "^1.0.3" + is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" @@ -9164,11 +8263,6 @@ is-typed-array@^1.1.3: foreach "^2.0.5" has-symbols "^1.0.1" -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" @@ -9186,11 +8280,6 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -9198,11 +8287,6 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" @@ -9213,11 +8297,6 @@ isarray@^2.0.5: resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== -isbinaryfile@^4.0.8: - version "4.0.10" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" - integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -9243,51 +8322,16 @@ isomorphic-ws@^5.0.0: resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: +istanbul-lib-coverage@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - istanbul-lib-coverage@^3.2.2: version "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-hook@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz" - integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== - dependencies: - append-transform "^2.0.0" - -istanbul-lib-instrument@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== - dependencies: - "@babel/core" "^7.7.5" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" - semver "^6.3.0" - -istanbul-lib-processinfo@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz" - integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== - dependencies: - archy "^1.0.0" - cross-spawn "^7.0.0" - istanbul-lib-coverage "^3.0.0-alpha.1" - make-dir "^3.0.0" - p-map "^3.0.0" - rimraf "^3.0.0" - uuid "^3.3.3" - istanbul-lib-report@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" @@ -9306,15 +8350,6 @@ istanbul-lib-report@^3.0.1: make-dir "^4.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - istanbul-lib-source-maps@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" @@ -9324,14 +8359,6 @@ istanbul-lib-source-maps@^4.0.1: istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" -istanbul-reports@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz" - integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - istanbul-reports@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" @@ -9555,15 +8582,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-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - jmespath@0.15.0: version "0.15.0" resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz" @@ -9579,17 +8597,12 @@ js-sha3@0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-string-escape@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.14.1, js-yaml@^3.10.0, js-yaml@^3.13.1: +js-yaml@3.14.1, js-yaml@^3.10.0: version "3.14.1" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -9631,11 +8644,6 @@ jsdom@^23.0.1: ws "^8.14.2" xml-name-validator "^5.0.0" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - json-buffer@3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" @@ -9646,7 +8654,7 @@ json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: +json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -9692,13 +8700,6 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -9735,114 +8736,11 @@ jsonpointer@^5.0.0: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== -just-extend@^4.0.2: - version "4.2.1" - resolved "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz" - integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== - jwt-simple@0.5.6: version "0.5.6" resolved "https://registry.npmjs.org/jwt-simple/-/jwt-simple-0.5.6.tgz" integrity sha512-40aUybvhH9t2h71ncA1/1SbtTNCVZHgsTsTgqPUxGWDmUDrXyDf2wMNQKEbdBjbf4AI+fQhbECNTV6lWxQKUzg== -karma-chai@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/karma-chai/-/karma-chai-0.1.0.tgz#bee5ad40400517811ae34bb945f762909108b79a" - integrity sha512-mqKCkHwzPMhgTYca10S90aCEX9+HjVjjrBFAsw36Zj7BlQNbokXXCAe6Ji04VUMsxcY5RLP7YphpfO06XOubdg== - -karma-chrome-launcher@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" - integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== - dependencies: - which "^1.2.1" - -karma-cli@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-2.0.0.tgz#481548d28661af4cc68f3d8e09708f17d2cba931" - integrity sha512-1Kb28UILg1ZsfqQmeELbPzuEb5C6GZJfVIk0qOr8LNYQuYWmAaqP16WpbpKEjhejDrDYyYOwwJXSZO6u7q5Pvw== - dependencies: - resolve "^1.3.3" - -karma-electron@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/karma-electron/-/karma-electron-7.3.0.tgz#269897d2566262e6ddc594a3d408b84275014a5c" - integrity sha512-JCwAZxtzLo+Qk6HD8MqlU+c6mB7A5jZYNb+ftbMNxutnmi1hzb8/wIqJzpw087R7jV5ZzNHujMq8mStI5n4Q6Q== - dependencies: - async "~3.2.2" - combine-source-map "~0.8.0" - commander "~2.9.0" - convert-source-map "~1.2.0" - js-string-escape "~1.0.0" - minstache "~1.2.0" - xtend "~4.0.1" - -karma-firefox-launcher@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz#9a38cc783c579a50f3ed2a82b7386186385cfc2d" - integrity sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA== - dependencies: - is-wsl "^2.2.0" - which "^2.0.1" - -karma-mocha@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" - integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== - dependencies: - minimist "^1.2.3" - -karma-spec-reporter@^0.0.36: - version "0.0.36" - resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.36.tgz#c54dc155dec2ded1f92ea68dbbdd67fcedbef350" - integrity sha512-11bvOl1x6ryKZph7kmbmMpbi8vsngEGxGOoeTlIcDaH3ab3j8aPJnZ+r+K/SS0sBSGy5VGkGYO2+hLct7hw/6w== - dependencies: - colors "1.4.0" - -karma-webpack@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" - integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - webpack-merge "^4.1.5" - -karma@^6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" - integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== - dependencies: - "@colors/colors" "1.5.0" - body-parser "^1.19.0" - braces "^3.0.2" - chokidar "^3.5.1" - connect "^3.7.0" - di "^0.0.1" - dom-serialize "^2.2.1" - glob "^7.1.7" - graceful-fs "^4.2.6" - http-proxy "^1.18.1" - isbinaryfile "^4.0.8" - lodash "^4.17.21" - log4js "^6.4.1" - mime "^2.5.2" - minimatch "^3.0.4" - mkdirp "^0.5.5" - qjobs "^1.2.0" - range-parser "^1.2.1" - rimraf "^3.0.2" - socket.io "^4.4.1" - source-map "^0.6.1" - tmp "^0.2.1" - ua-parser-js "^0.7.30" - yargs "^16.1.1" - -keypress@0.1.x: - version "0.1.0" - resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a" - integrity sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA== - keyv@^4.0.0, keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -10096,11 +8994,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - loady@~0.0.5: version "0.0.5" resolved "https://registry.npmjs.org/loady/-/loady-0.0.5.tgz" @@ -10184,16 +9077,6 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" @@ -10204,11 +9087,6 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== -lodash.memoize@~3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" - integrity sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A== - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -10244,7 +9122,7 @@ lodash.zip@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" integrity sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg== -lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10265,17 +9143,6 @@ log-symbols@^5.1.0: chalk "^5.0.0" is-unicode-supported "^1.1.0" -log4js@^6.4.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.6.0.tgz#e8fd00143d1e0ecf1d10959bb69b90b1b30137f3" - integrity sha512-3v8R7fd45UB6THucSht6wN2/7AZEruQbXdjygPZcxt5TA/msO6si9CN5MefUuKXbYnJHTBnYcx4famwcyQd+sA== - dependencies: - date-format "^4.0.11" - debug "^4.3.4" - flatted "^3.2.5" - rfdc "^1.3.0" - streamroller "^3.1.1" - logform@^2.3.2, logform@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" @@ -10366,13 +9233,13 @@ magic-string@^0.30.3, magic-string@^0.30.5: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magicast@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.2.tgz#42dcade5573ed8f10f5540f9d04964e21dba9130" - integrity sha512-Fjwkl6a0syt9TFN0JSYpOybxiMCkYNEeOTnOTNRbjphirLakznZXAqrXgj/7GG3D1dvETONNwrBfinvAbpunDg== +magicast@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.3.tgz#a15760f982deec9dabc5f314e318d7c6bddcb27b" + integrity sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw== dependencies: - "@babel/parser" "^7.23.3" - "@babel/types" "^7.23.3" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" source-map-js "^1.0.2" make-dir@4.0.0, make-dir@^4.0.0: @@ -10390,7 +9257,7 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2: +make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -10519,11 +9386,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -10582,7 +9444,7 @@ micro-ftch@^0.3.1: resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== -micromatch@^4.0.0, micromatch@^4.0.4: +micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -10603,14 +9465,14 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" -mime@2.6.0, mime@^2.5.2: +mime@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== @@ -10674,6 +9536,13 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -10702,13 +9571,6 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -10718,7 +9580,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -10822,13 +9684,6 @@ minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: minipass "^3.0.0" yallist "^4.0.0" -minstache@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minstache/-/minstache-1.2.0.tgz#ff1cc403ac2844f68dbf18c662129be7eb0efc41" - integrity sha512-VSAeaiKXHIKifdNHCalWmFvChtLrNirwhDZd0yeEO57WXCT+uJYN3RPAusvLi3z7VlwFBBtDX80bG7aHkcMAmg== - dependencies: - commander "1.0.4" - mitt@3.0.0, mitt@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" @@ -10839,7 +9694,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -"mkdirp@>=0.5 0", mkdirp@^0.5.5: +"mkdirp@>=0.5 0": version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -10925,15 +9780,10 @@ mortice@^3.0.1: p-queue "^7.2.0" p-timeout "^6.0.0" -mrmime@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" - integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== - -ms@2.0.0: +mrmime@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== ms@2.1.2: version "2.1.2" @@ -11039,12 +9889,12 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.3, negotiator@^0.6.2, negotiator@^0.6.3: +negotiator@^0.6.2, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0, neo-async@^2.6.2: +neo-async@^2.6.0: version "2.6.2" resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -11059,17 +9909,6 @@ nice-try@^1.0.4: resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nise@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.4.tgz#491ce7e7307d4ec546f5a659b2efe94a18b4bbc0" - integrity sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg== - dependencies: - "@sinonjs/commons" "^2.0.0" - "@sinonjs/fake-timers" "^10.0.2" - "@sinonjs/text-encoding" "^0.7.1" - just-extend "^4.0.2" - path-to-regexp "^1.7.0" - node-addon-api@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" @@ -11199,18 +10038,6 @@ node-machine-id@1.1.12: resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== -node-preload@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz" - integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== - dependencies: - process-on-spawn "^1.0.0" - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - node-stdlib-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz#5ddcfdf4063b88fb282979a1aa6ddab9728d5e4c" @@ -11513,40 +10340,7 @@ nx@16.9.0, "nx@>=16.5.1 < 17": "@nx/nx-win32-arm64-msvc" "16.9.0" "@nx/nx-win32-x64-msvc" "16.9.0" -nyc@^15.1.0: - version "15.1.0" - resolved "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz" - integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== - dependencies: - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - caching-transform "^4.0.0" - convert-source-map "^1.7.0" - decamelize "^1.2.0" - find-cache-dir "^3.2.0" - find-up "^4.1.0" - foreground-child "^2.0.0" - get-package-type "^0.1.0" - glob "^7.1.6" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-hook "^3.0.0" - istanbul-lib-instrument "^4.0.0" - istanbul-lib-processinfo "^2.0.2" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.0.2" - make-dir "^3.0.0" - node-preload "^0.2.1" - p-map "^3.0.0" - process-on-spawn "^1.0.0" - resolve-from "^5.0.0" - rimraf "^3.0.0" - signal-exit "^3.0.2" - spawn-wrap "^2.0.0" - test-exclude "^6.0.0" - yargs "^15.0.2" - -object-assign@^4, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -11642,20 +10436,6 @@ on-exit-leak-free@^2.1.0: resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -11855,13 +10635,6 @@ p-map@4.0.0, p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== - dependencies: - aggregate-error "^3.0.0" - p-pipe@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" @@ -11953,16 +10726,6 @@ pac-resolver@^7.0.0: ip "^1.1.8" netmask "^2.0.2" -package-hash@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz" - integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== - dependencies: - graceful-fs "^4.1.15" - hasha "^5.0.0" - lodash.flattendeep "^4.4.0" - release-zalgo "^1.0.0" - pacote@^15.2.0: version "15.2.0" resolved "https://registry.yarnpkg.com/pacote/-/pacote-15.2.0.tgz#0f0dfcc3e60c7b39121b2ac612bf8596e95344d3" @@ -12054,11 +10817,6 @@ parse5@^7.1.2: dependencies: entities "^4.4.0" -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - path-browserify@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz" @@ -12117,13 +10875,6 @@ path-scurry@^1.10.1, path-scurry@^1.6.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -12232,7 +10983,7 @@ pino@^8.12.0: sonic-boom "^3.1.0" thread-stream "^2.0.0" -pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -12310,13 +11061,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process-on-spawn@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz" - integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== - dependencies: - fromentries "^1.2.0" - process-warning@^2.0.0, process-warning@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626" @@ -12542,18 +11286,6 @@ puppeteer-core@^20.9.0: devtools-protocol "0.0.1147663" ws "8.13.0" -qjobs@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" - integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== - -qs@6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== - dependencies: - side-channel "^1.0.4" - qs@^6.11.0, qs@^6.11.1: version "6.11.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" @@ -12616,11 +11348,6 @@ race-signal@^1.0.1, race-signal@^1.0.2: resolved "https://registry.yarnpkg.com/race-signal/-/race-signal-1.0.2.tgz#e42379fba0cec4ee8dab7c9bbbd4aa6e0d14c25f" integrity sha512-o3xNv0iTcIDQCXFlF6fPAMEBRjFxssgGoRqLbg06m+AdzEXXLUmoNOoUHTVz2NoBI8hHwKFKoC6IqyNtWr2bww== -rambda@^7.4.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/rambda/-/rambda-7.5.0.tgz#1865044c59bc0b16f63026c6e5a97e4b1bbe98fe" - integrity sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA== - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" @@ -12636,26 +11363,11 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - rate-limiter-flexible@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/rate-limiter-flexible/-/rate-limiter-flexible-4.0.0.tgz#4754706216f0b442e7527b1367e42b7682145010" integrity sha512-SkA18LEPqJJKHixi6E7tzBKTXbj9gu5wPyfTykPVRZR5JGSw0dMCjtZsjlfuabVY940pu28Wu87NZN4FhztnyQ== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -12838,13 +11550,6 @@ regexpp@^3.0.0: resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -release-zalgo@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz" - integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= - dependencies: - es6-error "^4.0.1" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -12855,11 +11560,6 @@ require-from-string@^2.0.2: resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -12892,14 +11592,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve-typescript-plugin@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/resolve-typescript-plugin/-/resolve-typescript-plugin-2.0.1.tgz#ae4a1a81372b1e3389239268ac774bcc2780f4e3" - integrity sha512-n0FdUHSo8vkT6omKdE+Gda7api6PzIwsoYH4RTH0tUpRq46hk8dOcWZpzBwpoJyjSz3OxHIC/hKGL8LB8B09GQ== - dependencies: - tslib "2.5.0" - -resolve@^1.10.0, resolve@^1.22.1, resolve@^1.3.3: +resolve@^1.10.0, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -12924,14 +11617,6 @@ resolve@^1.17.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - responselike@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" @@ -13205,24 +11890,6 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - scrypt-js@3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" @@ -13238,7 +11905,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -13250,7 +11917,7 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -13283,13 +11950,6 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serialize-javascript@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" - integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== - dependencies: - randombytes "^2.1.0" - set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" @@ -13405,42 +12065,13 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sinon-chai@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783" - integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g== - -sinon@^15.0.3: - version "15.0.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-15.0.3.tgz#38005fcd80827177b6aa0245f82401d9ec88994b" - integrity sha512-si3geiRkeovP7Iel2O+qGL4NrO9vbMf3KsrJEi0ghP1l5aBkB5UxARea5j0FUsSqH3HLBh0dQPAyQ8fObRUqHw== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers" "^10.0.2" - "@sinonjs/samsam" "^8.0.0" - diff "^5.1.0" - nise "^5.1.4" - supports-color "^7.2.0" - -sinon@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-16.0.0.tgz#06da4e63624b946c9d7e67cce21c2f67f40f23a9" - integrity sha512-B8AaZZm9CT5pqe4l4uWJztfD/mOTa7dL8Qo0W4+s+t74xECOgSZDDQCBjNgIK3+n4kyxQrSTv2V5ul8K25qkiQ== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers" "^10.3.0" - "@sinonjs/samsam" "^8.0.0" - diff "^5.1.0" - nise "^5.1.4" - supports-color "^7.2.0" - -sirv@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.3.tgz#ca5868b87205a74bef62a469ed0296abceccd446" - integrity sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA== +sirv@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== dependencies: - "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" totalist "^3.0.0" slash@3.0.0, slash@^3.0.0: @@ -13477,32 +12108,6 @@ snappyjs@^0.7.0: resolved "https://registry.yarnpkg.com/snappyjs/-/snappyjs-0.7.0.tgz#6096eac06382700ae7fdefa579dea5e2aa20f51c" integrity sha512-u5iEEXkMe2EInQio6Wv9LWHOQYRDbD2O9hzS27GpT/lwfIQhTCnHCTqedqHIHe9ZcvQo+9au6vngQayipz1NYw== -socket.io-adapter@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6" - integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== - -socket.io-parser@~4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df" - integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig== - dependencies: - "@types/component-emitter" "^1.2.10" - component-emitter "~1.3.0" - debug "~4.3.1" - -socket.io@^4.4.1: - version "4.5.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.1.tgz#aa7e73f8a6ce20ee3c54b2446d321bbb6b1a9029" - integrity sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ== - dependencies: - accepts "~1.3.4" - base64id "~2.0.0" - debug "~4.3.2" - engine.io "~6.2.0" - socket.io-adapter "~2.4.0" - socket.io-parser "~4.0.4" - socks-proxy-agent@^6.0.0: version "6.1.1" resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz" @@ -13565,7 +12170,7 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-support@^0.5.21, source-map-support@~0.5.20: +source-map-support@^0.5.21: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -13573,28 +12178,11 @@ source-map-support@^0.5.21, source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.5.0, source-map@~0.5.3: - version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -spawn-wrap@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz" - integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== - dependencies: - foreground-child "^2.0.0" - is-windows "^1.0.2" - make-dir "^3.0.0" - rimraf "^3.0.0" - signal-exit "^3.0.2" - which "^2.0.1" - spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -13710,11 +12298,6 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - std-env@^3.5.0: version "3.6.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.6.0.tgz#94807562bddc68fa90f2e02c5fd5b6865bb4e98e" @@ -13778,15 +12361,6 @@ stream-to-it@^0.2.2: dependencies: get-iterator "^1.0.2" -streamroller@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.2.tgz#abd444560768b340f696307cf84d3f46e86c0e63" - integrity sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A== - dependencies: - date-format "^4.0.13" - debug "^4.3.4" - fs-extra "^8.1.0" - streamx@^2.15.0: version "2.15.1" resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6" @@ -14030,7 +12604,7 @@ supertest@^6.3.3: methods "^1.1.2" superagent "^8.0.5" -supports-color@8.1.1, supports-color@^8.0.0: +supports-color@8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -14044,7 +12618,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0, supports-color@^7.2.0: +supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -14074,7 +12648,7 @@ systeminformation@^5.17.12: resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.21.7.tgz#53ef75daaf5d756d015f4bb02e059126ccac74f2" integrity sha512-K3LjnajrazTLTD61+87DFg8IXFk5ljx6nSBqB8pQLtC1UPivAjDtTYGPZ8jaBFxcesPaCOkvLRtBq+RFscrsLw== -tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -14165,27 +12739,6 @@ temp-dir@1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== -terser-webpack-plugin@^5.3.7: - version "5.3.9" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" - integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.17" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.16.8" - -terser@^5.16.8: - version "5.18.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.2.tgz#ff3072a0faf21ffd38f99acc9a0ddf7b5f07b948" - integrity sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" @@ -14395,16 +12948,6 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.1.tgz#8144e811d44c749cd65b2da305a032510774452d" integrity sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A== -ts-loader@^9.4.4: - version "9.4.4" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" - integrity sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w== - dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.0.0" - micromatch "^4.0.0" - semver "^7.3.4" - ts-node@^10.8.1, ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -14458,11 +13001,6 @@ tslib@2.4.0, tslib@^2.3.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tslib@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - tslib@^1.10.0: version "1.14.1" resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" @@ -14529,7 +13067,7 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: +type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -14569,7 +13107,7 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== -type-fest@^0.8.0, type-fest@^0.8.1: +type-fest@^0.8.1: version "0.8.1" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -14584,14 +13122,6 @@ type-fest@^3.0.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.7.2.tgz#08f83ee3229b63077e95c9035034d32905969457" integrity sha512-f9BHrLjRJ4MYkfOsnC/53PNDzZJcVo14MqLp2+hXE39p5bgwqohxR5hDZztwxlbxmIVuvC2EFAKrAkokq23PLA== -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -14631,13 +13161,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -14661,11 +13184,6 @@ typescript-docs-verifier@^2.5.0: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== - ufo@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.1.tgz#e085842f4627c41d4c1b60ebea1f75cdab4ce86b" @@ -14783,11 +13301,6 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -14814,14 +13327,6 @@ upath@2.0.1: resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== -update-browserslist-db@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" - integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -14907,11 +13412,6 @@ util@^0.12.4, util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - uuid@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -14950,15 +13450,6 @@ v8-compile-cache@2.3.0: resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8-to-istanbul@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz#1b83ed4e397f58c85c266a570fc2558b5feb9265" - integrity sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - v8-to-istanbul@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" @@ -14990,15 +13481,10 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vary@^1: - version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vite-node@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.1.0.tgz#0ebcb7398692e378954786dfba28e905e28a76b4" - integrity sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q== +vite-node@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.2.1.tgz#bca96ae91b2b1ee9a7aa73685908362d70ce26a8" + integrity sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg== dependencies: cac "^6.7.14" debug "^4.3.4" @@ -15006,10 +13492,10 @@ vite-node@1.1.0: picocolors "^1.0.0" vite "^5.0.0" -vite-plugin-node-polyfills@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.18.0.tgz#2ad147960f7a35dbbb1c9f9c1ae928bd0f438c1e" - integrity sha512-zkdLD3gpOhLFyxYRMJ5apk0RcODhomuS3XQgExowiX8naoc251JfcP3toqnfDlMdF0xuPYahre/H38xAcq8ApA== +vite-plugin-node-polyfills@^0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.19.0.tgz#54338c47d29fa4c3a19fcd369001331290094c81" + integrity sha512-AhdVxAmVnd1doUlIRGUGV6ZRPfB9BvIwDF10oCOmL742IsvsFIAV4tSMxSfu5e0Px0QeJLgWVOSbtHIvblzqMw== dependencies: "@rollup/plugin-inject" "^5.0.5" node-stdlib-browser "^1.2.0" @@ -15034,22 +13520,22 @@ vite@^5.0.0: optionalDependencies: fsevents "~2.3.3" -vitest-when@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/vitest-when/-/vitest-when-0.3.0.tgz#663d4274f1e7302bd24ec00dda8269d20b2eff04" - integrity sha512-wYfmzd+GkvdNNhbeb/40PnKpetUP5I7qxvdbu1OAXRXaLrnLfSrJTa/dMIbqqrc8SA0vhonpw5p0RHDXwhDM1Q== +vitest-when@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/vitest-when/-/vitest-when-0.3.1.tgz#72db1c0a8e76fae81f8fc21c6da3c769f8e7f8bb" + integrity sha512-qZt4VmuvGtkLEqUpq5AJHQtdfhU8wJH+eXHk+WBo8kFT5zdfVV06+vFgYzvuSOq73srlCEsJ4VJqX7uBtOwWLg== -vitest@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.1.0.tgz#47ba67c564aa137b53b0197d2a992908e7f5b04d" - integrity sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A== - dependencies: - "@vitest/expect" "1.1.0" - "@vitest/runner" "1.1.0" - "@vitest/snapshot" "1.1.0" - "@vitest/spy" "1.1.0" - "@vitest/utils" "1.1.0" - acorn-walk "^8.3.0" +vitest@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.2.1.tgz#9afb705826a2c6260a71b625d28b49117833dce6" + integrity sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA== + dependencies: + "@vitest/expect" "1.2.1" + "@vitest/runner" "1.2.1" + "@vitest/snapshot" "1.2.1" + "@vitest/spy" "1.2.1" + "@vitest/utils" "1.2.1" + acorn-walk "^8.3.2" cac "^6.7.14" chai "^4.3.10" debug "^4.3.4" @@ -15063,7 +13549,7 @@ vitest@^1.1.0: tinybench "^2.5.1" tinypool "^0.8.1" vite "^5.0.0" - vite-node "1.1.0" + vite-node "1.2.1" why-is-node-running "^2.2.2" vm-browserify@^1.0.1: @@ -15071,11 +13557,6 @@ vm-browserify@^1.0.1: resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== - w3c-xmlserializer@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" @@ -15092,14 +13573,6 @@ wait-port@^1.0.4, wait-port@^1.1.0: commander "^9.3.0" debug "^4.3.4" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" @@ -15323,40 +13796,40 @@ web3@^4.0.3: web3-utils "^4.0.3" web3-validator "^1.0.2" -webdriver@8.27.0: - version "8.27.0" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-8.27.0.tgz#27e936a03c08b2d72ed6bd01a6a46f8189ef0abf" - integrity sha512-n1IA+rR3u84XxU9swiKUM06BkEC0GDimfZkBML57cny+utQOUbdM/mBpqCUnkWX/RBz/p2EfHdKNyOs3/REaog== +webdriver@8.28.0: + version "8.28.0" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-8.28.0.tgz#8d07eca1b23cc3dd46484ed3a91cbd256a5c6a77" + integrity sha512-1ASMK+sNfVh5rdaRRk+eFLIfae93ViXHJBpuJemeORwZkfOJNF2CNSZl5uK2e6+nzbkY2cjM6QsZwfhL3lCiRg== dependencies: "@types/node" "^20.1.0" "@types/ws" "^8.5.3" - "@wdio/config" "8.27.0" - "@wdio/logger" "8.24.12" + "@wdio/config" "8.28.0" + "@wdio/logger" "8.28.0" "@wdio/protocols" "8.24.12" - "@wdio/types" "8.27.0" - "@wdio/utils" "8.27.0" + "@wdio/types" "8.28.0" + "@wdio/utils" "8.28.0" deepmerge-ts "^5.1.0" got "^12.6.1" ky "^0.33.0" ws "^8.8.0" -webdriverio@^8.27.0: - version "8.27.0" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-8.27.0.tgz#4068b0164ab66bfb62d6eb6b8d97df2d140922d5" - integrity sha512-Qh5VCiBjEmxnmXcL1QEFoDzFqTtaWKrXriuU5G0yHKCModGAt2G7IHTkAok3CpmkVJfZpEvY630aP1MvgDtFhw== +webdriverio@^8.28.0: + version "8.28.0" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-8.28.0.tgz#ad94292b7b1466aac205d993a93da528c6665626" + integrity sha512-rRVE8pvcxAEqnhhC70oMFkUZ82YWbpXYyzKgfl2LKBue13AHaiN5qWncsJv29rqREIim0dNj6q2JuuUTDFm1gg== dependencies: "@types/node" "^20.1.0" - "@wdio/config" "8.27.0" - "@wdio/logger" "8.24.12" + "@wdio/config" "8.28.0" + "@wdio/logger" "8.28.0" "@wdio/protocols" "8.24.12" "@wdio/repl" "8.24.12" - "@wdio/types" "8.27.0" - "@wdio/utils" "8.27.0" + "@wdio/types" "8.28.0" + "@wdio/utils" "8.28.0" archiver "^6.0.0" aria-query "^5.0.0" css-shorthand-properties "^1.1.1" css-value "^0.0.1" - devtools-protocol "^0.0.1237913" + devtools-protocol "^0.0.1245094" grapheme-splitter "^1.0.2" import-meta-resolve "^4.0.0" is-plain-obj "^4.1.0" @@ -15368,7 +13841,7 @@ webdriverio@^8.27.0: resq "^1.9.1" rgb2hex "0.2.5" serialize-error "^11.0.1" - webdriver "8.27.0" + webdriver "8.28.0" webidl-conversions@^3.0.0: version "3.0.1" @@ -15380,48 +13853,6 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-merge@^4.1.5: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== - dependencies: - lodash "^4.17.15" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.88.2: - version "5.88.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" - integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.0" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - whatwg-encoding@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" @@ -15468,11 +13899,6 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - which-typed-array@^1.1.11: version "1.1.11" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" @@ -15509,7 +13935,7 @@ which-typed-array@^1.1.9: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -which@^1.2.1, which@^1.2.9: +which@^1.2.9: version "1.3.1" resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -15627,15 +14053,6 @@ workerpool@6.2.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -15667,16 +14084,6 @@ write-file-atomic@^2.4.2: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -15718,11 +14125,6 @@ ws@^8.14.2, ws@^8.8.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== -ws@~8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== - xml-name-validator@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" @@ -15769,11 +14171,6 @@ xxhash-wasm@1.0.2: resolved "https://registry.yarnpkg.com/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz#ecc0f813219b727af4d5f3958ca6becee2f2f1ff" integrity sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A== -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -15804,14 +14201,6 @@ yargs-parser@21.1.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -15827,7 +14216,7 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.1.1, yargs@^16.2.0: +yargs@16.2.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -15853,7 +14242,7 @@ yargs@17.7.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@17.7.2, yargs@^17.7.2: +yargs@17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -15866,23 +14255,6 @@ yargs@17.7.2, yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^15.0.2: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - yargs@^17.1.1: version "17.6.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541"