diff --git a/.changeset/sweet-lions-design.md b/.changeset/sweet-lions-design.md new file mode 100644 index 00000000000..582b7495bcb --- /dev/null +++ b/.changeset/sweet-lions-design.md @@ -0,0 +1,8 @@ +--- +"@smithy/fetch-http-handler": minor +"@smithy/node-http-handler": minor +"@smithy/util-stream": minor +"@smithy/types": minor +--- + +vitest compatibility diff --git a/.changeset/violet-ghosts-complain.md b/.changeset/violet-ghosts-complain.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/violet-ghosts-complain.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/Makefile b/Makefile index 101c2fbfcf2..b2239ebf453 100644 --- a/Makefile +++ b/Makefile @@ -11,10 +11,15 @@ generate-protocol-tests: ./gradlew :smithy-typescript-protocol-test-codegen:build rm -rf ./private/smithy-rpcv2-cbor cp -r ./smithy-typescript-protocol-test-codegen/build/smithyprojections/smithy-typescript-protocol-test-codegen/smithy-rpcv2-cbor/typescript-codegen ./private/smithy-rpcv2-cbor - cp ./packages/core/jest.config.js ./private/smithy-rpcv2-cbor + cp ./packages/core/vitest.config.ts ./private/smithy-rpcv2-cbor/vitest.config.js node ./scripts/post-protocol-test-codegen npx prettier --write ./private/smithy-rpcv2-cbor yarn test-protocols: - (cd ./private/smithy-rpcv2-cbor && npx jest) \ No newline at end of file + (cd ./private/smithy-rpcv2-cbor && npx vitest run --globals) + +turbo-clean: + @read -p "Are you sure you want to delete your local cache? [y/N]: " ans && [ $${ans:-N} = y ] + @echo "\nDeleted cache folders: \n--------" + @find . -name '.turbo' -type d -prune -print -exec rm -rf '{}' + && echo '\n' \ No newline at end of file diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index a64849c7e67..00000000000 --- a/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - projects: [ - "/lib/*/jest.config.js", - "/private/*/jest.config.js", - "/packages/*/jest.config.js", - ], -}; diff --git a/package.json b/package.json index 23a6fa0e3d2..2fb06812baa 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,8 @@ "extract:docs": "mkdir -p api-extractor-packages && turbo run extract:docs", "release": "yarn changeset publish", "build-test-packages": "./gradlew clean build && node ./scripts/build-generated-test-packages", - "g:jest": "cd $INIT_CWD && jest", - "g:karma": "cd $INIT_CWD && karma", - "g:tsc": "cd $INIT_CWD && tsc" + "g:tsc": "cd $INIT_CWD && tsc", + "g:vitest": "cd $INIT_CWD && vitest" }, "repository": { "type": "git", @@ -39,29 +38,33 @@ "@microsoft/api-extractor": "7.34.4", "@tsconfig/recommended": "1.0.2", "@types/jest": "28.1.3", + "@types/jsdom": "20.0.1", "@typescript-eslint/eslint-plugin": "7.8.0", "@typescript-eslint/parser": "7.8.0", "esbuild": "0.19.11", "eslint": "8.57.0", "eslint-plugin-simple-import-sort": "7.0.0", "eslint-plugin-tsdoc": "0.2.17", + "get-port": "^7.1.0", + "happy-dom": "14.12.3", "husky": "^4.2.3", "jest": "29.7.0", - "jest-environment-jsdom": "29.7.0", - "karma": "6.4.3", - "karma-chrome-launcher": "3.2.0", - "karma-firefox-launcher": "2.1.3", - "karma-jasmine": "5.1.0", - "karma-typescript": "5.5.4", - "karma-webpack": "5.0.1", "prettier": "3.2.5", "puppeteer": "^19.2.0", "ts-jest": "29.1.2", "turbo": "latest", "typescript": "~5.2.2", + "vite": "4.5.5", + "vitest": "0.34.6", "webpack": "5.91.0", "yarn": "1.22.22" }, + "overrides": { + "vite": "4.5.5" + }, + "resolutions": { + "vite": "4.5.5" + }, "workspaces": [ "packages/*", "smithy-typescript-ssdk-libs/*", diff --git a/packages/abort-controller/jest.config.js b/packages/abort-controller/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/abort-controller/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/abort-controller/package.json b/packages/abort-controller/package.json index 21495b73e92..6f3d8dbaffc 100644 --- a/packages/abort-controller/package.json +++ b/packages/abort-controller/package.json @@ -16,7 +16,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/abort-controller/src/AbortController.spec.ts b/packages/abort-controller/src/AbortController.spec.ts index 53849ade626..77229883c10 100644 --- a/packages/abort-controller/src/AbortController.spec.ts +++ b/packages/abort-controller/src/AbortController.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { AbortController } from "./AbortController"; import { AbortSignal } from "./AbortSignal"; diff --git a/packages/abort-controller/src/AbortSignal.spec.ts b/packages/abort-controller/src/AbortSignal.spec.ts index cbfb7610014..3412de1717a 100644 --- a/packages/abort-controller/src/AbortSignal.spec.ts +++ b/packages/abort-controller/src/AbortSignal.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { AbortController } from "./AbortController"; describe("AbortSignal", () => { @@ -13,7 +15,7 @@ describe("AbortSignal", () => { it("should invoke the onabort handler when the signal is aborted", () => { const controller = new AbortController(); const { signal } = controller; - const abortHandler = jest.fn(); + const abortHandler = vi.fn(); signal.onabort = abortHandler; expect(abortHandler.mock.calls.length).toBe(0); controller.abort(); @@ -23,7 +25,7 @@ describe("AbortSignal", () => { it("should not invoke the onabort handler multiple time", () => { const controller = new AbortController(); const { signal } = controller; - const abortHandler = jest.fn(); + const abortHandler = vi.fn(); signal.onabort = abortHandler; expect(abortHandler.mock.calls.length).toBe(0); controller.abort(); diff --git a/packages/abort-controller/vitest.config.ts b/packages/abort-controller/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/abort-controller/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/chunked-blob-reader-native/jest.config.js b/packages/chunked-blob-reader-native/jest.config.js deleted file mode 100644 index bd895a5df03..00000000000 --- a/packages/chunked-blob-reader-native/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testEnvironment: "jsdom", -}; diff --git a/packages/chunked-blob-reader-native/package.json b/packages/chunked-blob-reader-native/package.json index dc97316fca7..468ede4fb76 100644 --- a/packages/chunked-blob-reader-native/package.json +++ b/packages/chunked-blob-reader-native/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/chunked-blob-reader-native/src/index.spec.ts b/packages/chunked-blob-reader-native/src/index.spec.ts index 290696968bb..b44a29ae256 100644 --- a/packages/chunked-blob-reader-native/src/index.spec.ts +++ b/packages/chunked-blob-reader-native/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { blobReader } from "./index"; describe("blobReader", () => { diff --git a/packages/chunked-blob-reader-native/vitest.config.ts b/packages/chunked-blob-reader-native/vitest.config.ts new file mode 100644 index 00000000000..44808064872 --- /dev/null +++ b/packages/chunked-blob-reader-native/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/chunked-blob-reader/jest.config.js b/packages/chunked-blob-reader/jest.config.js deleted file mode 100644 index bd895a5df03..00000000000 --- a/packages/chunked-blob-reader/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testEnvironment: "jsdom", -}; diff --git a/packages/chunked-blob-reader/package.json b/packages/chunked-blob-reader/package.json index f8fe8487aa0..fa281b829b1 100644 --- a/packages/chunked-blob-reader/package.json +++ b/packages/chunked-blob-reader/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/chunked-blob-reader/src/index.spec.ts b/packages/chunked-blob-reader/src/index.spec.ts index 79a5aa924ea..d9b47a30806 100644 --- a/packages/chunked-blob-reader/src/index.spec.ts +++ b/packages/chunked-blob-reader/src/index.spec.ts @@ -1,4 +1,5 @@ import { Blob as BlobPolyfill } from "buffer"; +import { describe, expect, test as it } from "vitest"; import { blobReader } from "./index"; diff --git a/packages/chunked-blob-reader/vitest.config.ts b/packages/chunked-blob-reader/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/chunked-blob-reader/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/config-resolver/jest.config.js b/packages/config-resolver/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/config-resolver/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/config-resolver/package.json b/packages/config-resolver/package.json index ad2062f78a8..c1378431dea 100644 --- a/packages/config-resolver/package.json +++ b/packages/config-resolver/package.json @@ -11,8 +11,9 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest", - "extract:docs": "api-extractor run --local" + "test": "yarn g:vitest run", + "extract:docs": "api-extractor run --local", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/config-resolver/src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.spec.ts b/packages/config-resolver/src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.spec.ts index af1799001eb..af12f26110a 100644 --- a/packages/config-resolver/src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.spec.ts @@ -1,4 +1,5 @@ import { booleanSelector, SelectorType } from "@smithy/util-config-provider"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { CONFIG_USE_DUALSTACK_ENDPOINT, @@ -7,23 +8,23 @@ import { NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, } from "./NodeUseDualstackEndpointConfigOptions"; -jest.mock("@smithy/util-config-provider"); +vi.mock("@smithy/util-config-provider"); describe("NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); const test = (func: Function, obj: Record, key: string, type: SelectorType) => { it.each([true, false, undefined])("returns %s", (output) => { - (booleanSelector as jest.Mock).mockReturnValueOnce(output); + vi.mocked(booleanSelector).mockReturnValueOnce(output); expect(func(obj)).toEqual(output); expect(booleanSelector).toBeCalledWith(obj, key, type); }); it("throws error", () => { const mockError = new Error("error"); - (booleanSelector as jest.Mock).mockImplementationOnce(() => { + vi.mocked(booleanSelector).mockImplementationOnce(() => { throw mockError; }); expect(() => { diff --git a/packages/config-resolver/src/endpointsConfig/NodeUseFipsEndpointConfigOptions.spec.ts b/packages/config-resolver/src/endpointsConfig/NodeUseFipsEndpointConfigOptions.spec.ts index e9f98c2c19d..ebf8b94e63a 100644 --- a/packages/config-resolver/src/endpointsConfig/NodeUseFipsEndpointConfigOptions.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/NodeUseFipsEndpointConfigOptions.spec.ts @@ -1,4 +1,5 @@ import { booleanSelector, SelectorType } from "@smithy/util-config-provider"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { CONFIG_USE_FIPS_ENDPOINT, @@ -7,23 +8,23 @@ import { NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, } from "./NodeUseFipsEndpointConfigOptions"; -jest.mock("@smithy/util-config-provider"); +vi.mock("@smithy/util-config-provider"); describe("NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); const test = (func: Function, obj: Record, key: string, type: SelectorType) => { it.each([true, false, undefined])("returns %s", (output) => { - (booleanSelector as jest.Mock).mockReturnValueOnce(output); + vi.mocked(booleanSelector).mockReturnValueOnce(output); expect(func(obj)).toEqual(output); expect(booleanSelector).toBeCalledWith(obj, key, type); }); it("throws error", () => { const mockError = new Error("error"); - (booleanSelector as jest.Mock).mockImplementationOnce(() => { + vi.mocked(booleanSelector).mockImplementationOnce(() => { throw mockError; }); expect(() => { diff --git a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts index c78960d4047..5a0d9e2af9a 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts @@ -1,8 +1,9 @@ import { normalizeProvider } from "@smithy/util-middleware"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { resolveCustomEndpointsConfig } from "./resolveCustomEndpointsConfig"; -jest.mock("@smithy/util-middleware"); +vi.mock("@smithy/util-middleware"); describe(resolveCustomEndpointsConfig.name, () => { const mockEndpoint = { @@ -13,18 +14,18 @@ describe(resolveCustomEndpointsConfig.name, () => { const mockInput = { endpoint: mockEndpoint, - urlParser: jest.fn(() => mockEndpoint), + urlParser: vi.fn(() => mockEndpoint), useDualstackEndpoint: () => Promise.resolve(false), } as any; beforeEach(() => { - (normalizeProvider as jest.Mock).mockImplementation((input) => + vi.mocked(normalizeProvider).mockImplementation((input) => typeof input === "function" ? input : () => Promise.resolve(input) ); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("tls", () => { diff --git a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts index cc8605fbd4e..a13580ae8bd 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { normalizeProvider } from "@smithy/util-middleware"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { resolveEndpointsConfig } from "./resolveEndpointsConfig"; import { getEndpointFromRegion } from "./utils/getEndpointFromRegion"; -jest.mock("@smithy/util-middleware"); -jest.mock("./utils/getEndpointFromRegion"); +vi.mock("@smithy/util-middleware"); +vi.mock("./utils/getEndpointFromRegion"); describe(resolveEndpointsConfig.name, () => { const mockEndpoint = { @@ -16,20 +17,20 @@ describe(resolveEndpointsConfig.name, () => { const mockInput = { endpoint: mockEndpoint, - urlParser: jest.fn(() => mockEndpoint), + urlParser: vi.fn(() => mockEndpoint), useDualstackEndpoint: () => Promise.resolve(false), useFipsEndpoint: () => Promise.resolve(false), } as any; beforeEach(() => { - (getEndpointFromRegion as jest.Mock).mockResolvedValueOnce(mockEndpoint); - (normalizeProvider as jest.Mock).mockImplementation((input) => + vi.mocked(getEndpointFromRegion).mockResolvedValueOnce(mockEndpoint); + vi.mocked(normalizeProvider).mockImplementation((input) => typeof input === "function" ? input : () => Promise.resolve(input) ); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("tls", () => { diff --git a/packages/config-resolver/src/endpointsConfig/utils/getEndpointFromRegion.spec.ts b/packages/config-resolver/src/endpointsConfig/utils/getEndpointFromRegion.spec.ts index 7e40182a21a..b5ef3290294 100644 --- a/packages/config-resolver/src/endpointsConfig/utils/getEndpointFromRegion.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/utils/getEndpointFromRegion.spec.ts @@ -1,11 +1,13 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getEndpointFromRegion } from "./getEndpointFromRegion"; describe(getEndpointFromRegion.name, () => { - const mockRegion = jest.fn(); - const mockUrlParser = jest.fn(); - const mockRegionInfoProvider = jest.fn(); - const mockUseFipsEndpoint = jest.fn(); - const mockUseDualstackEndpoint = jest.fn(); + const mockRegion = vi.fn(); + const mockUrlParser = vi.fn(); + const mockRegionInfoProvider = vi.fn(); + const mockUseFipsEndpoint = vi.fn(); + const mockUseDualstackEndpoint = vi.fn(); const mockInput = { region: mockRegion, @@ -33,7 +35,7 @@ describe(getEndpointFromRegion.name, () => { afterEach(() => { expect(mockRegion).toHaveBeenCalledTimes(1); - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("tls", () => { diff --git a/packages/config-resolver/src/regionConfig/config.spec.ts b/packages/config-resolver/src/regionConfig/config.spec.ts index 580f3e85280..0d85d0eca80 100644 --- a/packages/config-resolver/src/regionConfig/config.spec.ts +++ b/packages/config-resolver/src/regionConfig/config.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { NODE_REGION_CONFIG_FILE_OPTIONS, NODE_REGION_CONFIG_OPTIONS, diff --git a/packages/config-resolver/src/regionConfig/getRealRegion.spec.ts b/packages/config-resolver/src/regionConfig/getRealRegion.spec.ts index 5a27f4aa830..c0eae0d0428 100644 --- a/packages/config-resolver/src/regionConfig/getRealRegion.spec.ts +++ b/packages/config-resolver/src/regionConfig/getRealRegion.spec.ts @@ -1,21 +1,23 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getRealRegion } from "./getRealRegion"; import { isFipsRegion } from "./isFipsRegion"; -jest.mock("./isFipsRegion"); +vi.mock("./isFipsRegion"); describe(getRealRegion.name, () => { beforeEach(() => { - (isFipsRegion as jest.Mock).mockReturnValue(true); + vi.mocked(isFipsRegion).mockReturnValue(true); }); afterEach(() => { expect(isFipsRegion).toHaveBeenCalledTimes(1); - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns provided region if it's not FIPS", () => { const mockRegion = "mockRegion"; - (isFipsRegion as jest.Mock).mockReturnValue(false); + vi.mocked(isFipsRegion).mockReturnValue(false); expect(getRealRegion(mockRegion)).toStrictEqual(mockRegion); }); diff --git a/packages/config-resolver/src/regionConfig/isFipsRegion.spec.ts b/packages/config-resolver/src/regionConfig/isFipsRegion.spec.ts index a497e75f266..165ae8130b9 100644 --- a/packages/config-resolver/src/regionConfig/isFipsRegion.spec.ts +++ b/packages/config-resolver/src/regionConfig/isFipsRegion.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isFipsRegion } from "./isFipsRegion"; describe(isFipsRegion.name, () => { diff --git a/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts b/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts index cd01e207779..c788007dbf6 100644 --- a/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts +++ b/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts @@ -1,9 +1,11 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getRealRegion } from "./getRealRegion"; import { isFipsRegion } from "./isFipsRegion"; import { resolveRegionConfig } from "./resolveRegionConfig"; -jest.mock("./getRealRegion"); -jest.mock("./isFipsRegion"); +vi.mock("./getRealRegion"); +vi.mock("./isFipsRegion"); describe("RegionConfig", () => { const mockRegion = "mockRegion"; @@ -11,12 +13,12 @@ describe("RegionConfig", () => { const mockUseFipsEndpoint = () => Promise.resolve(false); beforeEach(() => { - (getRealRegion as jest.Mock).mockReturnValue(mockRealRegion); - (isFipsRegion as jest.Mock).mockReturnValue(false); + vi.mocked(getRealRegion).mockReturnValue(mockRealRegion); + vi.mocked(isFipsRegion).mockReturnValue(false); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("region", () => { @@ -49,8 +51,8 @@ describe("RegionConfig", () => { let mockUseFipsEndpoint; beforeEach(() => { - mockRegionProvider = jest.fn().mockResolvedValueOnce(Promise.resolve(mockRegion)); - mockUseFipsEndpoint = jest.fn().mockResolvedValueOnce(Promise.resolve(false)); + mockRegionProvider = vi.fn().mockResolvedValueOnce(Promise.resolve(mockRegion)); + mockUseFipsEndpoint = vi.fn().mockResolvedValueOnce(Promise.resolve(false)); }); afterEach(() => { @@ -68,7 +70,7 @@ describe("RegionConfig", () => { }); it("returns Provider which returns true for FIPS endpoints", async () => { - (isFipsRegion as jest.Mock).mockReturnValue(true); + vi.mocked(isFipsRegion).mockReturnValue(true); const resolvedRegionConfig = resolveRegionConfig({ region: mockRegionProvider, useFipsEndpoint: mockUseFipsEndpoint, diff --git a/packages/config-resolver/src/regionInfo/getHostnameFromVariants.spec.ts b/packages/config-resolver/src/regionInfo/getHostnameFromVariants.spec.ts index ed2fa8dea83..60e9279256f 100644 --- a/packages/config-resolver/src/regionInfo/getHostnameFromVariants.spec.ts +++ b/packages/config-resolver/src/regionInfo/getHostnameFromVariants.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { EndpointVariant } from "./EndpointVariant"; import { getHostnameFromVariants, GetHostnameFromVariantsOptions } from "./getHostnameFromVariants"; diff --git a/packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts b/packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts index 963444746b6..7dd84b6ad1d 100644 --- a/packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts +++ b/packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getHostnameFromVariants } from "./getHostnameFromVariants"; import { getRegionInfo } from "./getRegionInfo"; import { getResolvedHostname } from "./getResolvedHostname"; @@ -6,10 +8,10 @@ import { getResolvedSigningRegion } from "./getResolvedSigningRegion"; import { PartitionHash } from "./PartitionHash"; import { RegionHash } from "./RegionHash"; -jest.mock("./getHostnameFromVariants"); -jest.mock("./getResolvedHostname"); -jest.mock("./getResolvedPartition"); -jest.mock("./getResolvedSigningRegion"); +vi.mock("./getHostnameFromVariants"); +vi.mock("./getResolvedHostname"); +vi.mock("./getResolvedPartition"); +vi.mock("./getResolvedSigningRegion"); describe(getRegionInfo.name, () => { const mockPartition = "mockPartition"; @@ -63,17 +65,17 @@ describe(getRegionInfo.name, () => { }); beforeEach(() => { - (getHostnameFromVariants as jest.Mock).mockReturnValue(mockHostname); - (getResolvedHostname as jest.Mock).mockReturnValue(mockHostname); - (getResolvedPartition as jest.Mock).mockReturnValue(mockPartition); - (getResolvedSigningRegion as jest.Mock).mockReturnValue(undefined); + vi.mocked(getHostnameFromVariants).mockReturnValue(mockHostname); + vi.mocked(getResolvedHostname).mockReturnValue(mockHostname); + vi.mocked(getResolvedPartition).mockReturnValue(mockPartition); + vi.mocked(getResolvedSigningRegion).mockReturnValue(undefined); }); afterEach(() => { expect(getHostnameFromVariants).toHaveBeenCalledTimes(2); expect(getResolvedHostname).toHaveBeenCalledTimes(1); expect(getResolvedPartition).toHaveBeenCalledTimes(1); - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("returns data based on options passed", () => { @@ -88,8 +90,8 @@ describe(getRegionInfo.name, () => { const mockRegionHostname = mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname; const mockPartitionHostname = mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname; - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockRegionHostname); - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockPartitionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockRegionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockPartitionHostname); expect(getRegionInfo(mockRegion, mockGetRegionInfoOptions)).toEqual({ signingService: mockSigningService, @@ -132,7 +134,7 @@ describe(getRegionInfo.name, () => { it.each(Object.values(RegionCase))("%s", (regionCase) => { const mockSigningRegion = "mockSigningRegion"; - (getResolvedSigningRegion as jest.Mock).mockReturnValueOnce(mockSigningRegion); + vi.mocked(getResolvedSigningRegion).mockReturnValueOnce(mockSigningRegion); const mockRegionHash = getMockRegionHash(regionCase); const mockPartitionHash = getMockPartitionHash(regionCase); @@ -143,8 +145,8 @@ describe(getRegionInfo.name, () => { const mockRegionHostname = mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname; const mockPartitionHostname = mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname; - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockRegionHostname); - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockPartitionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockRegionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockPartitionHostname); const mockRegionHashWithSigningRegion = getMockRegionHashWithSigningRegion( regionCase, @@ -207,8 +209,8 @@ describe(getRegionInfo.name, () => { const mockRegionHostname = mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname; const mockPartitionHostname = mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname; - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockRegionHostname); - (getHostnameFromVariants as jest.Mock).mockReturnValueOnce(mockPartitionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockRegionHostname); + vi.mocked(getHostnameFromVariants).mockReturnValueOnce(mockPartitionHostname); const mockRegionHashWithSigningRegion = getMockRegionHashWithSigningService( regionCase, @@ -237,7 +239,7 @@ describe(getRegionInfo.name, () => { }); it("throws error if hostname is not defined", () => { - (getResolvedHostname as jest.Mock).mockReturnValueOnce(undefined); + vi.mocked(getResolvedHostname).mockReturnValueOnce(undefined); const mockRegionHash = getMockRegionHash(RegionCase.REGION); const mockPartitionHash = getMockPartitionHash(RegionCase.REGION); expect(() => { diff --git a/packages/config-resolver/src/regionInfo/getResolvedHostname.spec.ts b/packages/config-resolver/src/regionInfo/getResolvedHostname.spec.ts index e9dc444415a..9cdbf24f78e 100644 --- a/packages/config-resolver/src/regionInfo/getResolvedHostname.spec.ts +++ b/packages/config-resolver/src/regionInfo/getResolvedHostname.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { getResolvedHostname } from "./getResolvedHostname"; describe(getResolvedHostname.name, () => { @@ -5,7 +7,7 @@ describe(getResolvedHostname.name, () => { const mockHostname = "{region}.mockHostname.com"; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns hostname if available in regionHostname", () => { diff --git a/packages/config-resolver/src/regionInfo/getResolvedPartition.spec.ts b/packages/config-resolver/src/regionInfo/getResolvedPartition.spec.ts index e6083c41971..080cac64db9 100644 --- a/packages/config-resolver/src/regionInfo/getResolvedPartition.spec.ts +++ b/packages/config-resolver/src/regionInfo/getResolvedPartition.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { getResolvedPartition } from "./getResolvedPartition"; import { PartitionHash } from "./PartitionHash"; diff --git a/packages/config-resolver/src/regionInfo/getResolvedSigningRegion.spec.ts b/packages/config-resolver/src/regionInfo/getResolvedSigningRegion.spec.ts index ce55ef6d69f..55eaa648f6d 100644 --- a/packages/config-resolver/src/regionInfo/getResolvedSigningRegion.spec.ts +++ b/packages/config-resolver/src/regionInfo/getResolvedSigningRegion.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { getResolvedSigningRegion } from "./getResolvedSigningRegion"; describe(getResolvedSigningRegion.name, () => { @@ -22,7 +24,7 @@ describe(getResolvedSigningRegion.name, () => { }); it("regionRegex does not return a match in hostname", () => { - const matchSpy = jest.spyOn(String.prototype, "match").mockReturnValueOnce(null); + const matchSpy = vi.spyOn(String.prototype, "match").mockReturnValueOnce(null); expect(getResolvedSigningRegion(mockHostname, { ...mockOptions, useFipsEndpoint: true })).not.toBeDefined(); expect(matchSpy).toHaveBeenCalledTimes(1); diff --git a/packages/config-resolver/vitest.config.ts b/packages/config-resolver/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/config-resolver/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/core/jest.config.js b/packages/core/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/core/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/core/package.json b/packages/core/package.json index 054f359cc60..3addffbac10 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -9,10 +9,11 @@ "build:types:downlevel": "rimraf dist-types/ts3.4 && downlevel-dts dist-types dist-types/ts3.4", "stage-release": "rimraf ./.release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", - "lint": "npx eslint -c ../../.eslintrc.js \"src/**/*.ts\" && node ./scripts/lint", + "lint": "npx eslint -c ../../.eslintrc.js \"src/**/*.ts\" --fix && node ./scripts/lint", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --maxWorkers=1", - "test:cbor:perf": "node ./scripts/cbor-perf.mjs" + "test": "yarn g:vitest run", + "test:cbor:perf": "node ./scripts/cbor-perf.mjs", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/core/src/normalizeProvider.spec.ts b/packages/core/src/normalizeProvider.spec.ts index 8650d6f0b24..dd95bd05ab2 100644 --- a/packages/core/src/normalizeProvider.spec.ts +++ b/packages/core/src/normalizeProvider.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { normalizeProvider } from "./normalizeProvider"; describe(normalizeProvider.name, () => { diff --git a/packages/core/src/pagination/createPaginator.spec.ts b/packages/core/src/pagination/createPaginator.spec.ts index dccdf831712..6ab8085fc35 100644 --- a/packages/core/src/pagination/createPaginator.spec.ts +++ b/packages/core/src/pagination/createPaginator.spec.ts @@ -1,4 +1,5 @@ import { PaginationConfiguration } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { createPaginator } from "./createPaginator"; diff --git a/packages/core/src/setFeature.spec.ts b/packages/core/src/setFeature.spec.ts index 00e93c08fa6..86dfa779a2b 100644 --- a/packages/core/src/setFeature.spec.ts +++ b/packages/core/src/setFeature.spec.ts @@ -1,4 +1,5 @@ import { HandlerExecutionContext } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { setFeature } from "./setFeature"; diff --git a/packages/core/src/submodules/cbor/cbor.spec.ts b/packages/core/src/submodules/cbor/cbor.spec.ts index 9345b4bff81..82d6bc92721 100644 --- a/packages/core/src/submodules/cbor/cbor.spec.ts +++ b/packages/core/src/submodules/cbor/cbor.spec.ts @@ -1,6 +1,7 @@ import * as fs from "fs"; import JSONbig from "json-bigint"; import * as path from "path"; +import { describe, expect, test as it } from "vitest"; import { cbor } from "./cbor"; import { bytesToFloat16 } from "./cbor-decode"; diff --git a/packages/core/src/submodules/protocols/collect-stream-body.spec.ts b/packages/core/src/submodules/protocols/collect-stream-body.spec.ts index 58f911645d5..509246ce805 100644 --- a/packages/core/src/submodules/protocols/collect-stream-body.spec.ts +++ b/packages/core/src/submodules/protocols/collect-stream-body.spec.ts @@ -1,4 +1,5 @@ import { Uint8ArrayBlobAdapter } from "@smithy/util-stream"; +import { describe, expect, test as it } from "vitest"; import { collectBody } from "./collect-stream-body"; diff --git a/packages/core/src/submodules/protocols/extended-encode-uri-component.spec.ts b/packages/core/src/submodules/protocols/extended-encode-uri-component.spec.ts index ab21a39e6ff..5b507247061 100644 --- a/packages/core/src/submodules/protocols/extended-encode-uri-component.spec.ts +++ b/packages/core/src/submodules/protocols/extended-encode-uri-component.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { extendedEncodeURIComponent } from "./extended-encode-uri-component"; describe(extendedEncodeURIComponent.name, () => { diff --git a/packages/core/src/submodules/protocols/requestBuilder.spec.ts b/packages/core/src/submodules/protocols/requestBuilder.spec.ts index 652de31cca2..8a64fae9937 100644 --- a/packages/core/src/submodules/protocols/requestBuilder.spec.ts +++ b/packages/core/src/submodules/protocols/requestBuilder.spec.ts @@ -1,4 +1,5 @@ import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { requestBuilder } from "./requestBuilder"; diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/core/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/credential-provider-imds/jest.config.js b/packages/credential-provider-imds/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/credential-provider-imds/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/credential-provider-imds/package.json b/packages/credential-provider-imds/package.json index e52161a4534..c3a26e19bd7 100644 --- a/packages/credential-provider-imds/package.json +++ b/packages/credential-provider-imds/package.json @@ -14,7 +14,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "keywords": [ "aws", @@ -36,7 +37,6 @@ "@types/node": "^16.18.96", "concurrently": "7.0.0", "downlevel-dts": "0.10.1", - "nock": "^13.0.2", "rimraf": "3.0.2", "typedoc": "0.23.23" }, diff --git a/packages/credential-provider-imds/src/config/EndpointConfigOptions.spec.ts b/packages/credential-provider-imds/src/config/EndpointConfigOptions.spec.ts index 53e8815bbc9..cb0b18cd189 100644 --- a/packages/credential-provider-imds/src/config/EndpointConfigOptions.spec.ts +++ b/packages/credential-provider-imds/src/config/EndpointConfigOptions.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { CONFIG_ENDPOINT_NAME, ENDPOINT_CONFIG_OPTIONS, ENV_ENDPOINT_NAME } from "./EndpointConfigOptions"; describe("ENDPOINT_CONFIG_OPTIONS", () => { diff --git a/packages/credential-provider-imds/src/config/EndpointModeConfigOptions.spec.ts b/packages/credential-provider-imds/src/config/EndpointModeConfigOptions.spec.ts index 130fd44f0ae..331c1a63261 100644 --- a/packages/credential-provider-imds/src/config/EndpointModeConfigOptions.spec.ts +++ b/packages/credential-provider-imds/src/config/EndpointModeConfigOptions.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { EndpointMode } from "./EndpointMode"; import { CONFIG_ENDPOINT_MODE_NAME, diff --git a/packages/credential-provider-imds/src/fromContainerMetadata.spec.ts b/packages/credential-provider-imds/src/fromContainerMetadata.spec.ts index 0ff8830e12a..6db7c175876 100644 --- a/packages/credential-provider-imds/src/fromContainerMetadata.spec.ts +++ b/packages/credential-provider-imds/src/fromContainerMetadata.spec.ts @@ -1,3 +1,5 @@ +import { afterAll, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { ENV_CMDS_AUTH_TOKEN, ENV_CMDS_FULL_URI, @@ -8,7 +10,7 @@ import { httpRequest } from "./remoteProvider/httpRequest"; import { fromImdsCredentials, ImdsCredentials } from "./remoteProvider/ImdsCredentials"; const mockHttpRequest = httpRequest; -jest.mock("./remoteProvider/httpRequest"); +vi.mock("./remoteProvider/httpRequest"); const relativeUri = process.env[ENV_CMDS_RELATIVE_URI]; const fullUri = process.env[ENV_CMDS_FULL_URI]; diff --git a/packages/credential-provider-imds/src/fromInstanceMetadata.spec.ts b/packages/credential-provider-imds/src/fromInstanceMetadata.spec.ts index 3f23f674fd2..d6a860d8493 100644 --- a/packages/credential-provider-imds/src/fromInstanceMetadata.spec.ts +++ b/packages/credential-provider-imds/src/fromInstanceMetadata.spec.ts @@ -1,4 +1,5 @@ import { CredentialsProviderError } from "@smithy/property-provider"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { InstanceMetadataV1FallbackError } from "./error/InstanceMetadataV1FallbackError"; import { fromInstanceMetadata } from "./fromInstanceMetadata"; @@ -9,12 +10,12 @@ import { retry } from "./remoteProvider/retry"; import { getInstanceMetadataEndpoint } from "./utils/getInstanceMetadataEndpoint"; import { staticStabilityProvider } from "./utils/staticStabilityProvider"; -jest.mock("./remoteProvider/httpRequest"); -jest.mock("./remoteProvider/ImdsCredentials"); -jest.mock("./remoteProvider/retry"); -jest.mock("./remoteProvider/RemoteProviderInit"); -jest.mock("./utils/getInstanceMetadataEndpoint"); -jest.mock("./utils/staticStabilityProvider"); +vi.mock("./remoteProvider/httpRequest"); +vi.mock("./remoteProvider/ImdsCredentials"); +vi.mock("./remoteProvider/retry"); +vi.mock("./remoteProvider/RemoteProviderInit"); +vi.mock("./utils/getInstanceMetadataEndpoint"); +vi.mock("./utils/staticStabilityProvider"); describe("fromInstanceMetadata", () => { const hostname = "127.0.0.1"; @@ -58,27 +59,27 @@ describe("fromInstanceMetadata", () => { }); beforeEach(() => { - (staticStabilityProvider as jest.Mock).mockImplementation((input) => input); - (getInstanceMetadataEndpoint as jest.Mock).mockResolvedValue({ hostname }); - (isImdsCredentials as unknown as jest.Mock).mockReturnValue(true); - (providerConfigFromInit as jest.Mock).mockReturnValue({ + vi.mocked(staticStabilityProvider).mockImplementation((input) => input); + vi.mocked(getInstanceMetadataEndpoint).mockResolvedValue({ hostname } as any); + (isImdsCredentials as unknown as any).mockReturnValue(true); + vi.mocked(providerConfigFromInit).mockReturnValue({ timeout: mockTimeout, maxRetries: mockMaxRetries, }); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("gets token and profile name to fetch credentials", async () => { - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); await expect(fromInstanceMetadata()()).resolves.toEqual(mockCreds); expect(httpRequest).toHaveBeenCalledTimes(3); @@ -91,13 +92,13 @@ describe("fromInstanceMetadata", () => { }); it("trims profile returned name from IMDS", async () => { - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(" " + mockProfile + " ") - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce((" " + mockProfile + " ") as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); await expect(fromInstanceMetadata()()).resolves.toEqual(mockCreds); expect(httpRequest).toHaveBeenNthCalledWith(3, { @@ -107,7 +108,7 @@ describe("fromInstanceMetadata", () => { }); it("passes {} to providerConfigFromInit if init not defined", async () => { - (retry as jest.Mock).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); + vi.mocked(retry).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); await expect(fromInstanceMetadata()()).resolves.toEqual(mockCreds); expect(providerConfigFromInit).toHaveBeenCalledTimes(1); @@ -115,7 +116,7 @@ describe("fromInstanceMetadata", () => { }); it("passes init to providerConfigFromInit", async () => { - (retry as jest.Mock).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); + vi.mocked(retry).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); const init = { maxRetries: 5, timeout: 1213 }; await expect(fromInstanceMetadata(init)()).resolves.toEqual(mockCreds); @@ -124,22 +125,22 @@ describe("fromInstanceMetadata", () => { }); it("passes maxRetries returned from providerConfigFromInit to retry", async () => { - (retry as jest.Mock).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); + vi.mocked(retry).mockResolvedValueOnce(mockProfile).mockResolvedValueOnce(mockCreds); await expect(fromInstanceMetadata()()).resolves.toEqual(mockCreds); expect(retry).toHaveBeenCalledTimes(2); - expect((retry as jest.Mock).mock.calls[0][1]).toBe(mockMaxRetries); - expect((retry as jest.Mock).mock.calls[1][1]).toBe(mockMaxRetries); + expect(vi.mocked(retry).mock.calls[0][1]).toBe(mockMaxRetries); + expect(vi.mocked(retry).mock.calls[1][1]).toBe(mockMaxRetries); }); it("throws CredentialsProviderError if credentials returned are incorrect", async () => { - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (isImdsCredentials as unknown as jest.Mock).mockReturnValueOnce(false); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + (isImdsCredentials as unknown as any).mockReturnValueOnce(false); await expect(fromInstanceMetadata()()).rejects.toEqual( new CredentialsProviderError("Invalid response received from instance metadata service.") @@ -153,8 +154,10 @@ describe("fromInstanceMetadata", () => { it("throws Error if httpRequest for profile fails", async () => { const mockError = new Error("profile not found"); - (httpRequest as jest.Mock).mockResolvedValueOnce(mockToken).mockRejectedValueOnce(mockError); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockRejectedValueOnce(mockError); + vi.mocked(retry).mockImplementation((fn: any) => fn()); await expect(fromInstanceMetadata()()).rejects.toEqual(mockError); expect(retry).toHaveBeenCalledTimes(1); @@ -163,11 +166,11 @@ describe("fromInstanceMetadata", () => { it("throws Error if httpRequest for credentials fails", async () => { const mockError = new Error("creds not found"); - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) .mockRejectedValueOnce(mockError); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); + vi.mocked(retry).mockImplementation((fn: any) => fn()); await expect(fromInstanceMetadata()()).rejects.toEqual(mockError); expect(retry).toHaveBeenCalledTimes(2); @@ -176,11 +179,11 @@ describe("fromInstanceMetadata", () => { }); it("throws SyntaxError if httpRequest returns unparseable creds", async () => { - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce("."); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce("." as any); + vi.mocked(retry).mockImplementation((fn: any) => fn()); await expect(fromInstanceMetadata()()).rejects.toThrow("Unexpected token"); expect(retry).toHaveBeenCalledTimes(2); @@ -192,39 +195,39 @@ describe("fromInstanceMetadata", () => { const tokenError = Object.assign(new Error("token not found"), { statusCode: 400, }); - (httpRequest as jest.Mock).mockRejectedValueOnce(tokenError); + vi.mocked(httpRequest).mockRejectedValueOnce(tokenError); await expect(fromInstanceMetadata()()).rejects.toEqual(tokenError); }); it("should call staticStabilityProvider with the credential loader", async () => { - (httpRequest as jest.Mock) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + vi.mocked(httpRequest) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); await fromInstanceMetadata()(); - expect(staticStabilityProvider as jest.Mock).toBeCalledTimes(1); + expect(vi.mocked(staticStabilityProvider)).toBeCalledTimes(1); }); describe("disables fetching of token", () => { beforeEach(() => { - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); }); it("when token fetch returns with TimeoutError", async () => { const tokenError = new Error("TimeoutError"); - (httpRequest as jest.Mock) + vi.mocked(httpRequest) .mockRejectedValueOnce(tokenError) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); const fromInstanceMetadataFunc = fromInstanceMetadata(); await expect(fromInstanceMetadataFunc()).resolves.toEqual(mockCreds); @@ -235,12 +238,12 @@ describe("fromInstanceMetadata", () => { it(`when token fetch errors with statusCode ${statusCode}`, async () => { const tokenError = Object.assign(new Error(), { statusCode }); - (httpRequest as jest.Mock) + vi.mocked(httpRequest) .mockRejectedValueOnce(tokenError) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); const fromInstanceMetadataFunc = fromInstanceMetadata(); await expect(fromInstanceMetadataFunc()).resolves.toEqual(mockCreds); @@ -252,16 +255,16 @@ describe("fromInstanceMetadata", () => { it("uses insecure data flow once, if error is not TimeoutError", async () => { const tokenError = new Error("Error"); - (httpRequest as jest.Mock) + vi.mocked(httpRequest) .mockRejectedValueOnce(tokenError) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); const fromInstanceMetadataFunc = fromInstanceMetadata(); await expect(fromInstanceMetadataFunc()).resolves.toEqual(mockCreds); @@ -271,35 +274,33 @@ describe("fromInstanceMetadata", () => { it("uses insecure data flow once, if error statusCode is not 400, 403, 404, 405", async () => { const tokenError = Object.assign(new Error("Error"), { statusCode: 406 }); - (httpRequest as jest.Mock) + vi.mocked(httpRequest) .mockRejectedValueOnce(tokenError) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)) - .mockResolvedValueOnce(mockToken) - .mockResolvedValueOnce(mockProfile) - .mockResolvedValueOnce(JSON.stringify(mockImdsCreds)); + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any) + .mockResolvedValueOnce(mockToken as any) + .mockResolvedValueOnce(mockProfile as any) + .mockResolvedValueOnce(JSON.stringify(mockImdsCreds) as any); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); const fromInstanceMetadataFunc = fromInstanceMetadata(); await expect(fromInstanceMetadataFunc()).resolves.toEqual(mockCreds); await expect(fromInstanceMetadataFunc()).resolves.toEqual(mockCreds); }); - // ToDo: Investigate why Jest29 throws TypeError: Class constructor cannot be invoked without 'new' - it.skip("allows blocking imdsv1 fallback", async () => { + it("allows blocking imdsv1 fallback", async () => { const tokenError = Object.assign(new Error("Error"), { statusCode: 406 }); - (httpRequest as jest.Mock).mockRejectedValueOnce(tokenError); + vi.mocked(httpRequest).mockRejectedValueOnce(tokenError); - (retry as jest.Mock).mockImplementation((fn: any) => fn()); - (fromImdsCredentials as jest.Mock).mockReturnValue(mockCreds); + vi.mocked(retry).mockImplementation((fn: any) => fn()); + vi.mocked(fromImdsCredentials).mockReturnValue(mockCreds); const fromInstanceMetadataFunc = fromInstanceMetadata({ ec2MetadataV1Disabled: true, }); - await fromInstanceMetadataFunc(); await expect(() => fromInstanceMetadataFunc()).rejects.toBeInstanceOf(InstanceMetadataV1FallbackError); }); }); diff --git a/packages/credential-provider-imds/src/remoteProvider/ImdsCredentials.spec.ts b/packages/credential-provider-imds/src/remoteProvider/ImdsCredentials.spec.ts index 53e8aecfab0..5d539d98850 100644 --- a/packages/credential-provider-imds/src/remoteProvider/ImdsCredentials.spec.ts +++ b/packages/credential-provider-imds/src/remoteProvider/ImdsCredentials.spec.ts @@ -1,4 +1,5 @@ import { AwsCredentialIdentity } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { fromImdsCredentials, ImdsCredentials, isImdsCredentials } from "./ImdsCredentials"; diff --git a/packages/credential-provider-imds/src/remoteProvider/RemoteProviderInit.spec.ts b/packages/credential-provider-imds/src/remoteProvider/RemoteProviderInit.spec.ts index c688dd5eb56..2877841029e 100644 --- a/packages/credential-provider-imds/src/remoteProvider/RemoteProviderInit.spec.ts +++ b/packages/credential-provider-imds/src/remoteProvider/RemoteProviderInit.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, providerConfigFromInit } from "./RemoteProviderInit"; describe("providerConfigFromInit", () => { diff --git a/packages/credential-provider-imds/src/remoteProvider/httpRequest.spec.ts b/packages/credential-provider-imds/src/remoteProvider/httpRequest.spec.ts index 15e037f5a7c..3ef01c315a5 100644 --- a/packages/credential-provider-imds/src/remoteProvider/httpRequest.spec.ts +++ b/packages/credential-provider-imds/src/remoteProvider/httpRequest.spec.ts @@ -1,96 +1,110 @@ import { ProviderError } from "@smithy/property-provider"; -import http, { createServer } from "http"; -import nock from "nock"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { httpRequest } from "./httpRequest"; +vi.mock("http", async () => { + const actual: any = vi.importActual("http"); + + const pkg = { + ...actual, + request: vi.fn(), + }; + return { + ...pkg, + default: pkg, + }; +}); + +import EventEmitter from "events"; +import { request } from "http"; + describe("httpRequest", () => { - const requestSpy = jest.spyOn(http, "request"); let port: number; const hostname = "localhost"; const path = "/"; - const getOpenPort = async (candidatePort = 4321): Promise => { - try { - return new Promise((resolve, reject) => { - const server = createServer(); - server.on("error", () => reject()); - server.listen(candidatePort); - server.close(() => resolve(candidatePort)); - }); - } catch (e) { - return await getOpenPort(candidatePort + 1); - } - }; - - beforeAll(async () => { - port = await getOpenPort(); - }); - afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); + function mockResponse({ expectedResponse, statusCode = 200 }: any) { + return vi.mocked(request).mockImplementationOnce((() => { + const request = Object.assign(new EventEmitter(), { + destroy: vi.fn(), + end: vi.fn(), + }); + const response = new EventEmitter() as any; + response.statusCode = statusCode; + setTimeout(() => { + request.emit("response", response); + setTimeout(() => { + response.emit("data", Buffer.from(expectedResponse)); + response.emit("end"); + }, 50); + }, 50); + return request; + }) as any); + } + describe("returns response", () => { it("defaults to method GET", async () => { const expectedResponse = "expectedResponse"; - const scope = nock(`http://${hostname}:${port}`).get(path).reply(200, expectedResponse); + + mockResponse({ expectedResponse }); const response = await httpRequest({ hostname, path, port }); expect(response.toString()).toStrictEqual(expectedResponse); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - scope.done(); }); it("uses method passed in options", async () => { const method = "POST"; const expectedResponse = "expectedResponse"; - const scope = nock(`http://${hostname}:${port}`).post(path).reply(200, expectedResponse); + mockResponse({ expectedResponse }); const response = await httpRequest({ hostname, path, port, method }); expect(response.toString()).toStrictEqual(expectedResponse); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - scope.done(); }); it("works with IPv6 hostname with encapsulated brackets", async () => { const expectedResponse = "expectedResponse"; const encapsulatedIPv6Hostname = "[::1]"; - const scope = nock(`http://${encapsulatedIPv6Hostname}:${port}`).get(path).reply(200, expectedResponse); + mockResponse({ expectedResponse }); const response = await httpRequest({ hostname: encapsulatedIPv6Hostname, path, port }); expect(response.toString()).toStrictEqual(expectedResponse); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - scope.done(); }); }); describe("throws error", () => { const errorOnStatusCode = async (statusCode: number) => { it(`statusCode: ${statusCode}`, async () => { - const scope = nock(`http://${hostname}:${port}`).get(path).reply(statusCode, "continue"); + mockResponse({ + statusCode, + expectedResponse: "continue", + }); await expect(httpRequest({ hostname, path, port })).rejects.toStrictEqual( Object.assign(new ProviderError("Error response received from instance metadata service"), { statusCode }) ); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - scope.done(); }); }; it("when request throws error", async () => { - const scope = nock(`http://${hostname}:${port}`).get(path).replyWithError("error"); + vi.mocked(request).mockImplementationOnce((() => { + const request = Object.assign(new EventEmitter(), { + destroy: vi.fn(), + end: vi.fn(), + }); + setTimeout(() => { + request.emit("error"); + }, 50); + return request; + }) as any); await expect(httpRequest({ hostname, path, port })).rejects.toStrictEqual( new ProviderError("Unable to connect to instance metadata service") ); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - scope.done(); }); describe("when request returns with statusCode < 200", () => { @@ -104,17 +118,21 @@ describe("httpRequest", () => { it("timeout", async () => { const timeout = 1000; - const scope = nock(`http://${hostname}:${port}`) - .get(path) - .delay(timeout * 2) - .reply(200, "expectedResponse"); + vi.mocked(request).mockImplementationOnce((() => { + const request = Object.assign(new EventEmitter(), { + destroy: vi.fn(), + end: vi.fn(), + }); + const response = new EventEmitter() as any; + response.statusCode = 200; + setTimeout(() => { + request.emit("timeout"); + }, 50); + return request; + }) as any); await expect(httpRequest({ hostname, path, port, timeout })).rejects.toStrictEqual( new ProviderError("TimeoutError from instance metadata service") ); - expect(requestSpy.mock.results[0].value.socket).toHaveProperty("destroyed", true); - - nock.abortPendingRequests(); - scope.done(); }); }); diff --git a/packages/credential-provider-imds/src/remoteProvider/retry.spec.ts b/packages/credential-provider-imds/src/remoteProvider/retry.spec.ts index c1b2f7d8b1d..daf8645b203 100644 --- a/packages/credential-provider-imds/src/remoteProvider/retry.spec.ts +++ b/packages/credential-provider-imds/src/remoteProvider/retry.spec.ts @@ -1,13 +1,15 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { retry } from "./retry"; describe("retry", () => { const successMsg = "Success"; const errorMsg = "Expected failure"; const retries = 10; - const retryable = jest.fn().mockRejectedValue(errorMsg); + const retryable = vi.fn().mockRejectedValue(errorMsg); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should retry a function the specified number of times", async () => { diff --git a/packages/credential-provider-imds/src/utils/getExtendedInstanceMetadataCredentials.spec.ts b/packages/credential-provider-imds/src/utils/getExtendedInstanceMetadataCredentials.spec.ts index 8ee4cdfa06f..77bd19b888b 100644 --- a/packages/credential-provider-imds/src/utils/getExtendedInstanceMetadataCredentials.spec.ts +++ b/packages/credential-provider-imds/src/utils/getExtendedInstanceMetadataCredentials.spec.ts @@ -1,20 +1,21 @@ import { Logger } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getExtendedInstanceMetadataCredentials } from "./getExtendedInstanceMetadataCredentials"; describe("getExtendedInstanceMetadataCredentials()", () => { - let nowMock: jest.SpyInstance; + let nowMock: any; const staticSecret = { accessKeyId: "key", secretAccessKey: "secret", }; const logger: Logger = { - warn: jest.fn(), + warn: vi.fn(), } as any; beforeEach(() => { - jest.spyOn(global.Math, "random"); - nowMock = jest.spyOn(Date, "now").mockReturnValueOnce(new Date("2022-02-22T00:00:00Z").getTime()); + vi.spyOn(global.Math, "random"); + nowMock = vi.spyOn(Date, "now").mockReturnValueOnce(new Date("2022-02-22T00:00:00Z").getTime()); }); afterEach(() => { @@ -23,7 +24,7 @@ describe("getExtendedInstanceMetadataCredentials()", () => { it("should extend the expiration random time(5~10 mins) from now", () => { const anyDate: Date = "any date" as unknown as Date; - (Math.random as jest.Mock).mockReturnValue(0.5); + (Math.random as any).mockReturnValue(0.5); expect(getExtendedInstanceMetadataCredentials({ ...staticSecret, expiration: anyDate }, logger)).toEqual({ ...staticSecret, originalExpiration: anyDate, diff --git a/packages/credential-provider-imds/src/utils/getInstanceMetadataEndpoint.spec.ts b/packages/credential-provider-imds/src/utils/getInstanceMetadataEndpoint.spec.ts index 13bd295f5e5..b0ec2f76719 100644 --- a/packages/credential-provider-imds/src/utils/getInstanceMetadataEndpoint.spec.ts +++ b/packages/credential-provider-imds/src/utils/getInstanceMetadataEndpoint.spec.ts @@ -1,5 +1,6 @@ import { loadConfig } from "@smithy/node-config-provider"; import { parseUrl } from "@smithy/url-parser"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { Endpoint } from "../config/Endpoint"; import { ENDPOINT_CONFIG_OPTIONS } from "../config/EndpointConfigOptions"; @@ -7,19 +8,19 @@ import { EndpointMode } from "../config/EndpointMode"; import { ENDPOINT_MODE_CONFIG_OPTIONS } from "../config/EndpointModeConfigOptions"; import { getInstanceMetadataEndpoint } from "./getInstanceMetadataEndpoint"; -jest.mock("@smithy/node-config-provider"); -jest.mock("@smithy/url-parser"); +vi.mock("@smithy/node-config-provider"); +vi.mock("@smithy/url-parser"); describe(getInstanceMetadataEndpoint.name, () => { let mockURL: string; const mockEndpoint = { protocol: "http:", hostname: "localhost", port: "80" }; beforeEach(() => { - (parseUrl as jest.Mock).mockReturnValue(mockEndpoint); + vi.mocked(parseUrl).mockReturnValue(mockEndpoint); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("when endpoint is defined", () => { @@ -33,8 +34,8 @@ describe(getInstanceMetadataEndpoint.name, () => { it("throws error when endpoint is invalid", () => { mockURL = "invalid_endpoint"; const mockError = new Error(`Invalid endpoint: ${mockURL}`); - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(mockURL)); - (parseUrl as jest.Mock).mockImplementation(() => { + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(mockURL)); + vi.mocked(parseUrl).mockImplementation(() => { throw mockError; }); return expect(getInstanceMetadataEndpoint()).rejects.toThrow(mockError); @@ -47,13 +48,13 @@ describe(getInstanceMetadataEndpoint.name, () => { it("with port", async () => { const mockPort = 80; mockURL = `${mockProtocol}://${mockHostname}:${mockPort}`; - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(mockURL)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(mockURL)); expect(await getInstanceMetadataEndpoint()).toStrictEqual(mockEndpoint); }); it("without port", async () => { mockURL = `${mockProtocol}://${mockHostname}`; - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(mockURL)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(mockURL)); expect(await getInstanceMetadataEndpoint()).toStrictEqual(mockEndpoint); }); }); @@ -61,7 +62,7 @@ describe(getInstanceMetadataEndpoint.name, () => { describe("when endpoint is not defined", () => { beforeEach(() => { - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(undefined)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(undefined)); }); afterEach(() => { @@ -74,7 +75,7 @@ describe(getInstanceMetadataEndpoint.name, () => { [Endpoint.IPv4, EndpointMode.IPv4], [Endpoint.IPv6, EndpointMode.IPv6], ])("returns %s when endpointMode=%s", async (endpoint, endpointMode) => { - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(endpointMode)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(endpointMode)); expect(await getInstanceMetadataEndpoint()).toEqual(mockEndpoint); expect(parseUrl).toHaveBeenCalledTimes(1); expect(parseUrl).toHaveBeenCalledWith(endpoint); @@ -82,7 +83,7 @@ describe(getInstanceMetadataEndpoint.name, () => { it(`throws Error when endpointMode is unsupported`, () => { const unsupportedEndpointMode = "unsupportedEndpointMode"; - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.resolve(unsupportedEndpointMode)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.resolve(unsupportedEndpointMode)); return expect(getInstanceMetadataEndpoint()).rejects.toThrowError( `Unsupported endpoint mode: ${unsupportedEndpointMode}.` + ` Select from ${Object.values(EndpointMode)}` ); @@ -90,7 +91,7 @@ describe(getInstanceMetadataEndpoint.name, () => { it(`rethrows Error when reading endpointMode throws error`, () => { const error = new Error("error"); - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.reject(error)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.reject(error)); return expect(getInstanceMetadataEndpoint()).rejects.toThrow(error); }); }); @@ -98,7 +99,7 @@ describe(getInstanceMetadataEndpoint.name, () => { describe("when reading endpoint throws error", () => { it("rethrows error", () => { const error = new Error("error"); - (loadConfig as jest.Mock).mockReturnValueOnce(() => Promise.reject(error)); + vi.mocked(loadConfig).mockReturnValueOnce(() => Promise.reject(error)); expect(getInstanceMetadataEndpoint()).rejects.toThrow(error); expect(loadConfig).toHaveBeenCalledTimes(1); expect(loadConfig).toHaveBeenCalledWith(ENDPOINT_CONFIG_OPTIONS); diff --git a/packages/credential-provider-imds/src/utils/staticStabilityProvider.spec.ts b/packages/credential-provider-imds/src/utils/staticStabilityProvider.spec.ts index e0e6cd4cdfd..58188b250ba 100644 --- a/packages/credential-provider-imds/src/utils/staticStabilityProvider.spec.ts +++ b/packages/credential-provider-imds/src/utils/staticStabilityProvider.spec.ts @@ -1,9 +1,10 @@ import { Logger } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getExtendedInstanceMetadataCredentials } from "./getExtendedInstanceMetadataCredentials"; import { staticStabilityProvider } from "./staticStabilityProvider"; -jest.mock("./getExtendedInstanceMetadataCredentials"); +vi.mock("./getExtendedInstanceMetadataCredentials"); describe("staticStabilityProvider", () => { const ONE_HOUR_IN_FUTURE = new Date(Date.now() + 60 * 60 * 1000); @@ -15,7 +16,7 @@ describe("staticStabilityProvider", () => { }; beforeEach(() => { - (getExtendedInstanceMetadataCredentials as jest.Mock).mockImplementation( + vi.mocked(getExtendedInstanceMetadataCredentials).mockImplementation( (() => { let extensionCount = 0; return (input) => { @@ -27,15 +28,15 @@ describe("staticStabilityProvider", () => { }; })() ); - jest.spyOn(global.console, "warn").mockImplementation(() => {}); + vi.spyOn(global.console, "warn").mockImplementation(() => {}); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("should refresh credentials if provider is functional", async () => { - const provider = jest.fn(); + const provider = vi.fn(); const stableProvider = staticStabilityProvider(provider); const repeat = 3; for (let i = 0; i < repeat; i++) { @@ -46,7 +47,7 @@ describe("staticStabilityProvider", () => { }); it("should throw if cannot load credentials at 1st load", async () => { - const provider = jest.fn().mockRejectedValue("Error"); + const provider = vi.fn().mockRejectedValue("Error"); try { await staticStabilityProvider(provider)(); fail("This provider should throw"); @@ -58,7 +59,7 @@ describe("staticStabilityProvider", () => { }); it("should extend expired credentials if refresh fails", async () => { - const provider = jest.fn().mockResolvedValueOnce(mockCreds).mockRejectedValue("Error"); + const provider = vi.fn().mockResolvedValueOnce(mockCreds).mockRejectedValue("Error"); const stableProvider = staticStabilityProvider(provider); expect(await stableProvider()).toEqual(mockCreds); const repeat = 3; @@ -76,7 +77,7 @@ describe("staticStabilityProvider", () => { it("should extend expired credentials if loaded expired credentials", async () => { const ONE_HOUR_AGO = new Date(Date.now() - 60 * 60 * 1000); - const provider = jest.fn().mockResolvedValue({ ...mockCreds, expiration: ONE_HOUR_AGO }); + const provider = vi.fn().mockResolvedValue({ ...mockCreds, expiration: ONE_HOUR_AGO }); const stableProvider = staticStabilityProvider(provider); const repeat = 3; for (let i = 0; i < repeat; i++) { @@ -88,8 +89,8 @@ describe("staticStabilityProvider", () => { }); it("should allow custom logger to print warning messages", async () => { - const provider = jest.fn().mockResolvedValueOnce(mockCreds).mockRejectedValue("Error"); - const logger = { warn: jest.fn() } as unknown as Logger; + const provider = vi.fn().mockResolvedValueOnce(mockCreds).mockRejectedValue("Error"); + const logger = { warn: vi.fn() } as unknown as Logger; const stableProvider = staticStabilityProvider(provider, { logger }); expect(await stableProvider()).toEqual(mockCreds); // load initial creds await stableProvider(); diff --git a/packages/credential-provider-imds/vitest.config.ts b/packages/credential-provider-imds/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/credential-provider-imds/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/eventstream-codec/jest.config.js b/packages/eventstream-codec/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/eventstream-codec/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/eventstream-codec/package.json b/packages/eventstream-codec/package.json index d42ac282268..5b0eb9371b0 100644 --- a/packages/eventstream-codec/package.json +++ b/packages/eventstream-codec/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --coverage" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/eventstream-codec/src/EventStreamCodec.spec.ts b/packages/eventstream-codec/src/EventStreamCodec.spec.ts index d046f9ba34b..512adbe1aef 100644 --- a/packages/eventstream-codec/src/EventStreamCodec.spec.ts +++ b/packages/eventstream-codec/src/EventStreamCodec.spec.ts @@ -1,4 +1,5 @@ import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { describe, expect, test as it } from "vitest"; import { EventStreamCodec } from "./EventStreamCodec"; import { vectors } from "./TestVectors.fixture"; diff --git a/packages/eventstream-codec/src/HeaderMarshaller.spec.ts b/packages/eventstream-codec/src/HeaderMarshaller.spec.ts index ca70ad00fab..897e93b9949 100644 --- a/packages/eventstream-codec/src/HeaderMarshaller.spec.ts +++ b/packages/eventstream-codec/src/HeaderMarshaller.spec.ts @@ -1,5 +1,6 @@ import { MessageHeaders } from "@smithy/types"; import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { describe, expect, test as it } from "vitest"; import { HeaderMarshaller } from "./HeaderMarshaller"; import { Int64 } from "./Int64"; diff --git a/packages/eventstream-codec/src/Int64.spec.ts b/packages/eventstream-codec/src/Int64.spec.ts index 48363d6c43d..a4ea32523bd 100644 --- a/packages/eventstream-codec/src/Int64.spec.ts +++ b/packages/eventstream-codec/src/Int64.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { Int64 } from "./Int64"; describe("Int64", () => { diff --git a/packages/eventstream-codec/src/MessageDecoderStream.spec.ts b/packages/eventstream-codec/src/MessageDecoderStream.spec.ts index 13e752fb15c..070d5e8fb11 100644 --- a/packages/eventstream-codec/src/MessageDecoderStream.spec.ts +++ b/packages/eventstream-codec/src/MessageDecoderStream.spec.ts @@ -1,4 +1,5 @@ import { Message } from "@smithy/types"; +import { describe, expect, test as it, vi } from "vitest"; import { MessageDecoderStream } from "./MessageDecoderStream"; @@ -15,11 +16,11 @@ describe("MessageDecoderStream", () => { }; const messageDecoderMock = { - decode: jest.fn().mockReturnValueOnce(message1).mockReturnValueOnce(message2), - feed: jest.fn(), - endOfStream: jest.fn(), - getMessage: jest.fn(), - getAvailableMessages: jest.fn(), + decode: vi.fn().mockReturnValueOnce(message1).mockReturnValueOnce(message2), + feed: vi.fn(), + endOfStream: vi.fn(), + getMessage: vi.fn(), + getAvailableMessages: vi.fn(), }; const inputStream = async function* () { diff --git a/packages/eventstream-codec/src/MessageEncoderStream.spec.ts b/packages/eventstream-codec/src/MessageEncoderStream.spec.ts index b8b1a4d583b..1f98e2a783d 100644 --- a/packages/eventstream-codec/src/MessageEncoderStream.spec.ts +++ b/packages/eventstream-codec/src/MessageEncoderStream.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { MessageEncoderStream } from "./MessageEncoderStream"; describe("MessageEncoderStream", () => { @@ -13,7 +15,7 @@ describe("MessageEncoderStream", () => { }; const messageEncoderMock = { - encode: jest.fn().mockReturnValueOnce(new Uint8Array(1)).mockReturnValueOnce(new Uint8Array(2)), + encode: vi.fn().mockReturnValueOnce(new Uint8Array(1)).mockReturnValueOnce(new Uint8Array(2)), }; const inputStream = async function* () { @@ -49,7 +51,7 @@ describe("MessageEncoderStream", () => { }; const messageEncoderMock = { - encode: jest.fn().mockReturnValueOnce(new Uint8Array(1)).mockReturnValueOnce(new Uint8Array(2)), + encode: vi.fn().mockReturnValueOnce(new Uint8Array(1)).mockReturnValueOnce(new Uint8Array(2)), }; const inputStream = async function* () { diff --git a/packages/eventstream-codec/src/SmithyMessageDecoderStream.spec.ts b/packages/eventstream-codec/src/SmithyMessageDecoderStream.spec.ts index 41be8bac272..67735515df4 100644 --- a/packages/eventstream-codec/src/SmithyMessageDecoderStream.spec.ts +++ b/packages/eventstream-codec/src/SmithyMessageDecoderStream.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { SmithyMessageDecoderStream } from "./SmithyMessageDecoderStream"; describe("SmithyMessageDecoderStream", () => { @@ -12,7 +14,7 @@ describe("SmithyMessageDecoderStream", () => { body: new Uint8Array(2), }; - const deserializer = jest + const deserializer = vi .fn() .mockReturnValueOnce(Promise.resolve("first")) .mockReturnValueOnce(Promise.resolve("second")); diff --git a/packages/eventstream-codec/src/SmithyMessageEncoderStream.spec.ts b/packages/eventstream-codec/src/SmithyMessageEncoderStream.spec.ts index f12e4567c47..6f87e1d920c 100644 --- a/packages/eventstream-codec/src/SmithyMessageEncoderStream.spec.ts +++ b/packages/eventstream-codec/src/SmithyMessageEncoderStream.spec.ts @@ -1,4 +1,5 @@ import { Message } from "@smithy/types"; +import { describe, expect, test as it, vi } from "vitest"; import { SmithyMessageEncoderStream } from "./SmithyMessageEncoderStream"; @@ -14,7 +15,7 @@ describe("SmithyMessageEncoderStream", () => { body: new Uint8Array(2), }; - const serializer = jest.fn().mockReturnValueOnce(message1).mockReturnValueOnce(message2); + const serializer = vi.fn().mockReturnValueOnce(message1).mockReturnValueOnce(message2); const inputStream = async function* () { yield "first"; diff --git a/packages/eventstream-codec/src/splitMessage.spec.ts b/packages/eventstream-codec/src/splitMessage.spec.ts index 0a1627d4b89..19f8b9e7d0d 100644 --- a/packages/eventstream-codec/src/splitMessage.spec.ts +++ b/packages/eventstream-codec/src/splitMessage.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { splitMessage } from "./splitMessage"; describe("splitMessage", () => { diff --git a/packages/eventstream-codec/vitest.config.ts b/packages/eventstream-codec/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/eventstream-codec/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/eventstream-serde-config-resolver/jest.config.js b/packages/eventstream-serde-config-resolver/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/eventstream-serde-config-resolver/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/eventstream-serde-config-resolver/package.json b/packages/eventstream-serde-config-resolver/package.json index d3197c86d4c..c63681e0295 100644 --- a/packages/eventstream-serde-config-resolver/package.json +++ b/packages/eventstream-serde-config-resolver/package.json @@ -11,8 +11,9 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest", - "extract:docs": "api-extractor run --local" + "test": "yarn g:vitest run", + "extract:docs": "api-extractor run --local", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts index c89eb402b5a..bb2ec2bf78e 100644 --- a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts +++ b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts @@ -1,10 +1,12 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { resolveEventStreamSerdeConfig } from "./EventStreamSerdeConfig"; describe("resolveEventStreamSerdeConfig", () => { - const eventStreamSerdeProvider = jest.fn(); + const eventStreamSerdeProvider = vi.fn(); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("sets value returned by eventStreamSerdeProvider", () => { diff --git a/packages/eventstream-serde-config-resolver/vitest.config.ts b/packages/eventstream-serde-config-resolver/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/eventstream-serde-config-resolver/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/eventstream-serde-node/jest.config.js b/packages/eventstream-serde-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/eventstream-serde-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/eventstream-serde-universal/jest.config.js b/packages/eventstream-serde-universal/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/eventstream-serde-universal/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/eventstream-serde-universal/package.json b/packages/eventstream-serde-universal/package.json index 5ff1ca19f28..7f27749a185 100644 --- a/packages/eventstream-serde-universal/package.json +++ b/packages/eventstream-serde-universal/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/eventstream-serde-universal/src/getChunkedStream.spec.ts b/packages/eventstream-serde-universal/src/getChunkedStream.spec.ts index 229a15dce61..b6c6620b8b7 100644 --- a/packages/eventstream-serde-universal/src/getChunkedStream.spec.ts +++ b/packages/eventstream-serde-universal/src/getChunkedStream.spec.ts @@ -1,4 +1,5 @@ import { Readable, ReadableOptions } from "stream"; +import { describe, expect, test as it } from "vitest"; import { getChunkedStream } from "./getChunkedStream"; diff --git a/packages/eventstream-serde-universal/src/getUnmarshalledStream.spec.ts b/packages/eventstream-serde-universal/src/getUnmarshalledStream.spec.ts index 3115d500934..8e9c7620d40 100644 --- a/packages/eventstream-serde-universal/src/getUnmarshalledStream.spec.ts +++ b/packages/eventstream-serde-universal/src/getUnmarshalledStream.spec.ts @@ -1,6 +1,7 @@ import { EventStreamCodec } from "@smithy/eventstream-codec"; import { Message } from "@smithy/types"; import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { describe, expect, test as it } from "vitest"; import { endEventMessage, exception, recordEventMessage, statsEventMessage } from "./getChunkedStream.spec"; import { getUnmarshalledStream } from "./getUnmarshalledStream"; diff --git a/packages/eventstream-serde-universal/vitest.config.ts b/packages/eventstream-serde-universal/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/eventstream-serde-universal/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/experimental-identity-and-auth/jest.config.integ.js b/packages/experimental-identity-and-auth/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/experimental-identity-and-auth/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/experimental-identity-and-auth/jest.config.js b/packages/experimental-identity-and-auth/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/experimental-identity-and-auth/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/experimental-identity-and-auth/package.json b/packages/experimental-identity-and-auth/package.json index e4183d766ed..5dd39818f48 100644 --- a/packages/experimental-identity-and-auth/package.json +++ b/packages/experimental-identity-and-auth/package.json @@ -11,8 +11,10 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --passWithNoTests", - "test:integration": "yarn g:jest --config jest.config.integ.js --passWithNoTests" + "test": "yarn g:vitest run --passWithNoTests", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch --passWithNoTests", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts b/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts index 496bd51236e..4edb570c2bc 100644 --- a/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts +++ b/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts @@ -4,7 +4,9 @@ import { OnlyHttpApiKeyAuthOptionalCommand, SameAsServiceCommand, } from "@smithy/identity-and-auth-http-api-key-auth-service"; -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, expect, test as it } from "vitest"; + +import { requireRequestsFrom } from "../../../../private/util-test/src/index"; describe("@httpApiKeyAuth integration tests", () => { // Match `HttpApiKeyAuthService` `@httpApiKeyAuth` trait diff --git a/packages/experimental-identity-and-auth/src/integration/httpBearerAuth.integ.spec.ts b/packages/experimental-identity-and-auth/src/integration/httpBearerAuth.integ.spec.ts index e0c04010ee0..78e5787ae67 100644 --- a/packages/experimental-identity-and-auth/src/integration/httpBearerAuth.integ.spec.ts +++ b/packages/experimental-identity-and-auth/src/integration/httpBearerAuth.integ.spec.ts @@ -4,7 +4,9 @@ import { OnlyHttpBearerAuthOptionalCommand, SameAsServiceCommand, } from "@smithy/identity-and-auth-http-bearer-auth-service"; -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, expect, test as it } from "vitest"; + +import { requireRequestsFrom } from "../../../../private/util-test/src/index"; describe("@httpBearerAuth integration tests", () => { // Arbitrary mock token diff --git a/packages/experimental-identity-and-auth/vitest.config.integ.ts b/packages/experimental-identity-and-auth/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/experimental-identity-and-auth/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/experimental-identity-and-auth/vitest.config.ts b/packages/experimental-identity-and-auth/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/experimental-identity-and-auth/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/fetch-http-handler/jest.config.js b/packages/fetch-http-handler/jest.config.js deleted file mode 100644 index e29c0e8a0cd..00000000000 --- a/packages/fetch-http-handler/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testEnvironment: "jsdom", - testPathIgnorePatterns: ["/node_modules/", "(.*).browser.spec.js"], -}; diff --git a/packages/fetch-http-handler/karma.conf.js b/packages/fetch-http-handler/karma.conf.js deleted file mode 100644 index 57889c7f4ba..00000000000 --- a/packages/fetch-http-handler/karma.conf.js +++ /dev/null @@ -1,32 +0,0 @@ -// Set up binary for Chromium browser in CHROME_BIN environment variable before running the test - -module.exports = function (config) { - config.set({ - frameworks: ["jasmine", "karma-typescript"], - files: [ - "src/stream-collector.ts", - "src/stream-collector.browser.spec.ts", - "src/fetch-http-handler.ts", - "src/fetch-http-handler.browser.spec.ts", - "src/request-timeout.ts", - ], - exclude: ["**/*.d.ts"], - preprocessors: { - "**/*.ts": "karma-typescript", - }, - reporters: ["progress", "karma-typescript"], - browsers: ["ChromeHeadlessNoSandbox"], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: "ChromeHeadless", - flags: ["--no-sandbox"], - }, - }, - karmaTypescriptConfig: { - bundlerOptions: { - addNodeGlobals: true, - }, - }, - singleRun: true, - }); -}; diff --git a/packages/fetch-http-handler/package.json b/packages/fetch-http-handler/package.json index 09003b8dc9d..a392da041cf 100644 --- a/packages/fetch-http-handler/package.json +++ b/packages/fetch-http-handler/package.json @@ -13,7 +13,10 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest --coverage --forceExit && yarn g:karma start karma.conf.js" + "test": "yarn g:vitest run && yarn test:browser", + "test:watch": "yarn g:vitest watch", + "test:browser": "yarn g:vitest run -c vitest.config.browser.ts", + "test:browser:watch": "yarn g:vitest watch -c vitest.config.browser.ts" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/fetch-http-handler/src/create-request.ts b/packages/fetch-http-handler/src/create-request.ts new file mode 100644 index 00000000000..ce95e3d289d --- /dev/null +++ b/packages/fetch-http-handler/src/create-request.ts @@ -0,0 +1,9 @@ +import { AdditionalRequestParameters } from "./fetch-http-handler"; + +/** + * @internal + * For mocking/interception. + */ +export function createRequest(url: string, requestOptions?: RequestInit & AdditionalRequestParameters) { + return new Request(url, requestOptions); +} diff --git a/packages/fetch-http-handler/src/fetch-http-handler.browser.spec.ts b/packages/fetch-http-handler/src/fetch-http-handler.browser.spec.ts index 19584b0412c..779a140ed72 100644 --- a/packages/fetch-http-handler/src/fetch-http-handler.browser.spec.ts +++ b/packages/fetch-http-handler/src/fetch-http-handler.browser.spec.ts @@ -1,9 +1,37 @@ import { HttpRequest } from "@smithy/protocol-http"; import { QueryParameterBag } from "@smithy/types"; +import { afterEach, beforeAll, describe, expect, test as it, vi } from "vitest"; + +import { createRequest } from "./create-request"; +import { FetchHttpHandler, keepAliveSupport } from "./fetch-http-handler"; + +vi.mock("./create-request", async () => { + return { + createRequest: vi.fn().mockImplementation((_url, options) => { + const url = new URL(_url); + return { + protocol: url.protocol, + hostname: url.hostname, + ...options, + } as any; + }), + }; +}); -import { FetchHttpHandler } from "./fetch-http-handler"; - -describe(FetchHttpHandler.name, () => { +vi.spyOn(global, "fetch").mockImplementation((async () => { + return { + headers: { + entries() { + return []; + }, + }, + async blob() { + return undefined; + }, + }; +}) as any); + +(typeof Blob === "function" ? describe : describe.skip)(FetchHttpHandler.name, () => { interface MockHttpRequestOptions { method?: string; body?: any; @@ -14,51 +42,56 @@ describe(FetchHttpHandler.name, () => { } const getMockHttpRequest = (options: MockHttpRequestOptions): HttpRequest => - new HttpRequest({ hostname: "example.com", ...options }); + new HttpRequest({ hostname: "localhost", protocol: "http", ...options }); describe("fetch", () => { + beforeAll(() => { + keepAliveSupport.supported = true; + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + it("sends basic fetch request", async () => { const fetchHttpHandler = new FetchHttpHandler(); - const winReqSpy = spyOn(window, "Request"); const mockHttpRequest = getMockHttpRequest({}); await fetchHttpHandler.handle(mockHttpRequest); const expectedUrl = `${mockHttpRequest.protocol}//${mockHttpRequest.hostname}/`; - const requestArgs = winReqSpy.calls.argsFor(0); + const requestArgs = vi.mocked(createRequest).mock.calls[0]; + expect(requestArgs[0]).toEqual(expectedUrl); - expect(requestArgs[1].method).toEqual(mockHttpRequest.method); - expect(requestArgs[1].keepalive).toEqual(false); + expect(requestArgs[1]!.method).toEqual(mockHttpRequest.method); + expect(requestArgs[1]!.keepalive).toEqual(false); }); for (const method of ["GET", "HEAD"]) { it(`sets body to undefined when method: '${method}'`, async () => { const fetchHttpHandler = new FetchHttpHandler(); - const winReqSpy = spyOn(window, "Request"); const mockHttpRequest = getMockHttpRequest({ method, body: "test" }); await fetchHttpHandler.handle(mockHttpRequest); - const requestArgs = winReqSpy.calls.argsFor(0); - expect(requestArgs[1].method).toEqual(mockHttpRequest.method); - expect(requestArgs[1].body).toEqual(undefined); + const requestArgs = vi.mocked(createRequest).mock.calls[0]; + expect(requestArgs[1]!.method).toEqual(mockHttpRequest.method); + expect(requestArgs[1]!.body).toEqual(undefined); }); } it(`sets keepalive to true if explicitly requested`, async () => { const fetchHttpHandler = new FetchHttpHandler({ keepAlive: true }); - const winReqSpy = spyOn(window, "Request"); const mockHttpRequest = getMockHttpRequest({}); await fetchHttpHandler.handle(mockHttpRequest); - const requestArgs = winReqSpy.calls.argsFor(0); - expect(requestArgs[1].keepalive).toEqual(true); + const requestArgs = vi.mocked(createRequest).mock.calls[0]; + expect(requestArgs[1]!.keepalive).toEqual(true); }); it(`builds querystring if provided`, async () => { const fetchHttpHandler = new FetchHttpHandler(); - const winReqSpy = spyOn(window, "Request"); const query = { foo: "bar" }; const fragment = "test"; @@ -68,22 +101,25 @@ describe(FetchHttpHandler.name, () => { const expectedUrl = `${mockHttpRequest.protocol}//${mockHttpRequest.hostname}/?${Object.entries(query) .map(([key, val]) => `${key}=${val}`) .join("&")}#${fragment}`; - const requestArgs = winReqSpy.calls.argsFor(0); + const requestArgs = vi.mocked(createRequest).mock.calls[0]; expect(requestArgs[0]).toEqual(expectedUrl); }); it(`sets auth if username/password are provided`, async () => { const fetchHttpHandler = new FetchHttpHandler(); - const winReqSpy = spyOn(window, "Request"); const username = "foo"; const password = "bar"; const mockHttpRequest = getMockHttpRequest({ username, password }); - await fetchHttpHandler.handle(mockHttpRequest); + await fetchHttpHandler.handle(mockHttpRequest).catch((error) => { + expect(String(error)).toContain( + "TypeError: Request cannot be constructed from a URL that includes credentials" + ); + }); const mockAuth = `${mockHttpRequest.username}:${mockHttpRequest.password}`; const expectedUrl = `${mockHttpRequest.protocol}//${mockAuth}@${mockHttpRequest.hostname}/`; - const requestArgs = winReqSpy.calls.argsFor(0); + const requestArgs = vi.mocked(createRequest).mock.calls[0]; expect(requestArgs[0]).toEqual(expectedUrl); }); }); diff --git a/packages/fetch-http-handler/src/fetch-http-handler.spec.ts b/packages/fetch-http-handler/src/fetch-http-handler.spec.ts index 1ef8fcced37..d8e7a308763 100644 --- a/packages/fetch-http-handler/src/fetch-http-handler.spec.ts +++ b/packages/fetch-http-handler/src/fetch-http-handler.spec.ts @@ -1,24 +1,25 @@ import { AbortController } from "@smithy/abort-controller"; import { HttpRequest } from "@smithy/protocol-http"; +import { afterAll, afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { FetchHttpHandler, keepAliveSupport } from "./fetch-http-handler"; import { requestTimeout } from "./request-timeout"; -const mockRequest = jest.fn(); -let timeoutSpy: jest.SpyInstance; +const mockRequest = vi.fn(); +let timeoutSpy: any; (global as any).Request = mockRequest; -(global as any).Headers = jest.fn(); +(global as any).Headers = vi.fn(); const globalFetch = global.fetch; -describe(FetchHttpHandler.name, () => { +(typeof Blob === "function" ? describe : describe.skip)(FetchHttpHandler.name, () => { beforeEach(() => { (global as any).AbortController = void 0; - jest.clearAllMocks(); + vi.clearAllMocks(); }); afterEach(() => { - jest.clearAllTimers(); + vi.clearAllTimers(); if (timeoutSpy) { timeoutSpy.mockRestore(); } @@ -31,14 +32,14 @@ describe(FetchHttpHandler.name, () => { it("makes requests using fetch", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob(["FOO"])), + blob: vi.fn().mockResolvedValue(new Blob(["FOO"])), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -52,14 +53,14 @@ describe(FetchHttpHandler.name, () => { it("put HttpClientConfig", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob(["FOO"])), + blob: vi.fn().mockResolvedValue(new Blob(["FOO"])), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -73,14 +74,14 @@ describe(FetchHttpHandler.name, () => { it("update HttpClientConfig", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob(["FOO"])), + blob: vi.fn().mockResolvedValue(new Blob(["FOO"])), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler({ requestTimeout: 200 }); @@ -101,14 +102,14 @@ describe(FetchHttpHandler.name, () => { const mockResponse = { body: null, headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob(["FOO"])), + blob: vi.fn().mockResolvedValue(new Blob(["FOO"])), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -122,14 +123,14 @@ describe(FetchHttpHandler.name, () => { it("properly constructs url", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; @@ -156,10 +157,10 @@ describe(FetchHttpHandler.name, () => { it("will omit body if method is GET", async () => { const mockResponse = { - headers: { entries: jest.fn().mockReturnValue([]) }, - blob: jest.fn().mockResolvedValue(new Blob()), + headers: { entries: vi.fn().mockReturnValue([]) }, + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; @@ -181,10 +182,10 @@ describe(FetchHttpHandler.name, () => { it("will omit body if method is HEAD", async () => { const mockResponse = { - headers: { entries: jest.fn().mockReturnValue([]) }, - blob: jest.fn().mockResolvedValue(new Blob()), + headers: { entries: vi.fn().mockReturnValue([]) }, + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; @@ -207,14 +208,14 @@ describe(FetchHttpHandler.name, () => { it("will not make request if already aborted", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -234,16 +235,16 @@ describe(FetchHttpHandler.name, () => { it("will pass abortSignal to fetch if supported", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; - (global as any).AbortController = jest.fn(); + (global as any).AbortController = vi.fn(); const fetchHttpHandler = new FetchHttpHandler(); await fetchHttpHandler.handle({} as any, { @@ -260,17 +261,17 @@ describe(FetchHttpHandler.name, () => { it("will pass timeout to request timeout", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; - timeoutSpy = jest.spyOn({ requestTimeout }, "requestTimeout"); + timeoutSpy = vi.spyOn({ requestTimeout }, "requestTimeout"); const fetchHttpHandler = new FetchHttpHandler({ requestTimeout: 500, }); @@ -287,10 +288,10 @@ describe(FetchHttpHandler.name, () => { }, blob: async () => new Blob(), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; - timeoutSpy = jest.spyOn({ requestTimeout }, "requestTimeout"); + timeoutSpy = vi.spyOn({ requestTimeout }, "requestTimeout"); const fetchHttpHandler = new FetchHttpHandler(async () => ({ requestTimeout: 500, })); @@ -301,7 +302,7 @@ describe(FetchHttpHandler.name, () => { }); it("will throw timeout error it timeout finishes before request", async () => { - const mockFetch = jest.fn(() => { + const mockFetch = vi.fn(() => { return new Promise(() => {}); }); (global as any).fetch = mockFetch; @@ -316,7 +317,7 @@ describe(FetchHttpHandler.name, () => { it("can be aborted before fetch completes", async () => { const abortController = new AbortController(); - const mockFetch = jest.fn(() => { + const mockFetch = vi.fn(() => { return new Promise(() => {}); }); (global as any).fetch = mockFetch; @@ -339,13 +340,13 @@ describe(FetchHttpHandler.name, () => { it("creates correct HTTPResponse object", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([["foo", "bar"]]), + entries: vi.fn().mockReturnValue([["foo", "bar"]]), }, - blob: jest.fn().mockResolvedValue(new Blob(["FOO"])), + blob: vi.fn().mockResolvedValue(new Blob(["FOO"])), status: 200, statusText: "foo", }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -362,10 +363,10 @@ describe(FetchHttpHandler.name, () => { "will pass credentials mode '%s' from a provider to a request", async (credentialsMode) => { const mockResponse = { - headers: { entries: jest.fn().mockReturnValue([]) }, - blob: jest.fn().mockResolvedValue(new Blob()), + headers: { entries: vi.fn().mockReturnValue([]) }, + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; @@ -398,14 +399,14 @@ describe(FetchHttpHandler.name, () => { it("will pass keepalive as false by default to request if supported", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler(); @@ -419,14 +420,14 @@ describe(FetchHttpHandler.name, () => { it("will pass keepalive to request if supported", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler({ keepAlive: true }); @@ -440,14 +441,14 @@ describe(FetchHttpHandler.name, () => { it("will not have keepalive property in request if not supported", async () => { const mockResponse = { headers: { - entries: jest.fn().mockReturnValue([ + entries: vi.fn().mockReturnValue([ ["foo", "bar"], ["bizz", "bazz"], ]), }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; mockRequest.mockImplementation(() => null); @@ -467,9 +468,9 @@ describe(FetchHttpHandler.name, () => { return []; }, }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler({ @@ -488,9 +489,9 @@ describe(FetchHttpHandler.name, () => { return []; }, }, - blob: jest.fn().mockResolvedValue(new Blob()), + blob: vi.fn().mockResolvedValue(new Blob()), }; - const mockFetch = jest.fn().mockResolvedValue(mockResponse); + const mockFetch = vi.fn().mockResolvedValue(mockResponse); (global as any).fetch = mockFetch; const fetchHttpHandler = new FetchHttpHandler({ @@ -528,17 +529,6 @@ describe(FetchHttpHandler.name, () => { // The Blob implementation does not implement Blob.text, so we deal with it here. async function blobToText(blob: Blob): Promise { - const reader = new FileReader(); - - return new Promise((resolve) => { - // This fires after the blob has been read/loaded. - reader.addEventListener("loadend", (e) => { - const text = e.target!.result as string; - resolve(text); - }); - - // Start reading the blob as text. - reader.readAsText(blob); - }); + return blob.text(); } }); diff --git a/packages/fetch-http-handler/src/fetch-http-handler.ts b/packages/fetch-http-handler/src/fetch-http-handler.ts index 6f0caac4fdc..dcd3dc05c97 100644 --- a/packages/fetch-http-handler/src/fetch-http-handler.ts +++ b/packages/fetch-http-handler/src/fetch-http-handler.ts @@ -3,6 +3,7 @@ import { buildQueryString } from "@smithy/querystring-builder"; import type { FetchHttpHandlerOptions } from "@smithy/types"; import { HeaderBag, HttpHandlerOptions, Provider } from "@smithy/types"; +import { createRequest } from "./create-request"; import { requestTimeout } from "./request-timeout"; declare let AbortController: any; @@ -22,7 +23,7 @@ export const keepAliveSupport = { /** * @internal */ -type AdditionalRequestParameters = { +export type AdditionalRequestParameters = { // This is required in Node.js when Request has a body, and does nothing in the browser. // Duplex: half means the request is fully transmitted before attempting to process the response. // As of writing this is the only accepted value in https://fetch.spec.whatwg.org/. @@ -62,7 +63,7 @@ export class FetchHttpHandler implements HttpHandler { } if (keepAliveSupport.supported === undefined) { keepAliveSupport.supported = Boolean( - typeof Request !== "undefined" && "keepalive" in new Request("https://[::1]") + typeof Request !== "undefined" && "keepalive" in createRequest("https://[::1]") ); } } @@ -139,7 +140,7 @@ export class FetchHttpHandler implements HttpHandler { let removeSignalEventListener = () => {}; - const fetchRequest = new Request(url, requestOptions); + const fetchRequest = createRequest(url, requestOptions); const raceOfPromises = [ fetch(fetchRequest).then((response) => { const fetchHeaders: any = response.headers; diff --git a/packages/fetch-http-handler/src/index.spec.ts b/packages/fetch-http-handler/src/index.spec.ts index f3f526fd13b..c404a2f5063 100644 --- a/packages/fetch-http-handler/src/index.spec.ts +++ b/packages/fetch-http-handler/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { FetchHttpHandler } from "./index"; describe("index", () => { diff --git a/packages/fetch-http-handler/src/stream-collector.browser.spec.ts b/packages/fetch-http-handler/src/stream-collector.browser.spec.ts index c8ded648ca0..025b19a804b 100644 --- a/packages/fetch-http-handler/src/stream-collector.browser.spec.ts +++ b/packages/fetch-http-handler/src/stream-collector.browser.spec.ts @@ -1,40 +1,38 @@ +import { describe, expect, test as it } from "vitest"; + import { streamCollector } from "./stream-collector"; describe("streamCollector", () => { - it("returns a Uint8Array from a blob", (done) => { + it("returns a Uint8Array from a blob", async () => { const expected = Uint8Array.from([102, 111, 111]); const dataPromise = new Response(expected.buffer).blob().then((blob) => streamCollector(blob)); - dataPromise.then((data: any) => { + await dataPromise.then((data: any) => { expect(data).toEqual(expected); - done(); }); }); - it("returns a Uint8Array from a ReadableStream", (done) => { + it("returns a Uint8Array from a ReadableStream", async () => { const expected = Uint8Array.from([102, 111, 111]); const dataPromise = streamCollector(new Response(expected.buffer).body); - dataPromise.then((data: any) => { + await dataPromise.then((data: any) => { expect(data).toEqual(expected); - done(); }); }); - it("returns a Uint8Array when stream is empty", (done) => { + it("returns a Uint8Array when stream is empty", async () => { const expected = new Uint8Array(0); const dataPromise = streamCollector(new Response(expected.buffer).body); - dataPromise.then((data: any) => { + await dataPromise.then((data: any) => { expect(data).toEqual(expected); - done(); }); }); - it("returns a Uint8Array when blob is empty", (done) => { + it("returns a Uint8Array when blob is empty", async () => { const expected = new Uint8Array(0); const dataPromise = new Response(expected.buffer).blob().then((blob) => streamCollector(blob)); - dataPromise.then((data: any) => { + await dataPromise.then((data: any) => { expect(data).toEqual(expected); - done(); }); }); }); diff --git a/packages/fetch-http-handler/src/stream-collector.spec.ts b/packages/fetch-http-handler/src/stream-collector.spec.ts index 77acc30d5b6..2d6395952df 100644 --- a/packages/fetch-http-handler/src/stream-collector.spec.ts +++ b/packages/fetch-http-handler/src/stream-collector.spec.ts @@ -1,4 +1,5 @@ import { Blob as BlobPolyfill } from "buffer"; +import { describe, expect, test as it } from "vitest"; import { streamCollector } from "./stream-collector"; diff --git a/packages/fetch-http-handler/src/stream-collector.ts b/packages/fetch-http-handler/src/stream-collector.ts index eefa5053734..1062a9d3e00 100644 --- a/packages/fetch-http-handler/src/stream-collector.ts +++ b/packages/fetch-http-handler/src/stream-collector.ts @@ -1,8 +1,8 @@ import { StreamCollector } from "@smithy/types"; export const streamCollector: StreamCollector = async (stream: Blob | ReadableStream): Promise => { - if (typeof Blob === "function" && stream instanceof Blob) { - return new Uint8Array(await stream.arrayBuffer()); + if ((typeof Blob === "function" && stream instanceof Blob) || stream.constructor?.name === "Blob") { + return new Uint8Array(await (stream as Blob).arrayBuffer()); } return collectStream(stream as ReadableStream); diff --git a/packages/fetch-http-handler/vitest.config.browser.ts b/packages/fetch-http-handler/vitest.config.browser.ts new file mode 100644 index 00000000000..44808064872 --- /dev/null +++ b/packages/fetch-http-handler/vitest.config.browser.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/fetch-http-handler/vitest.config.ts b/packages/fetch-http-handler/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/fetch-http-handler/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/hash-blob-browser/jest.config.js b/packages/hash-blob-browser/jest.config.js deleted file mode 100644 index bd895a5df03..00000000000 --- a/packages/hash-blob-browser/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testEnvironment: "jsdom", -}; diff --git a/packages/hash-blob-browser/karma.conf.js b/packages/hash-blob-browser/karma.conf.js deleted file mode 100644 index 1ef247459a0..00000000000 --- a/packages/hash-blob-browser/karma.conf.js +++ /dev/null @@ -1,26 +0,0 @@ -// Set up binary for Chromium browser in CHROME_BIN environment variable before running the test - -module.exports = function (config) { - config.set({ - frameworks: ["jasmine", "karma-typescript"], - files: ["src/**/*.ts"], - exclude: ["**/*.d.ts"], - preprocessors: { - "**/*.ts": "karma-typescript", - }, - reporters: ["progress", "karma-typescript"], - browsers: ["ChromeHeadlessNoSandbox"], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: "ChromeHeadless", - flags: ["--no-sandbox"], - }, - }, - karmaTypescriptConfig: { - bundlerOptions: { - addNodeGlobals: false, - }, - }, - singleRun: true, - }); -}; diff --git a/packages/hash-blob-browser/package.json b/packages/hash-blob-browser/package.json index 3be59089579..dff49269e33 100644 --- a/packages/hash-blob-browser/package.json +++ b/packages/hash-blob-browser/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:karma start karma.conf.js" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/hash-blob-browser/src/index.spec.ts b/packages/hash-blob-browser/src/index.spec.ts index 32daac76bfa..ea6e80f2fc7 100644 --- a/packages/hash-blob-browser/src/index.spec.ts +++ b/packages/hash-blob-browser/src/index.spec.ts @@ -1,4 +1,5 @@ import { toHex } from "@smithy/util-hex-encoding"; +import { describe, expect, test as it } from "vitest"; import { blobHasher } from "./index"; diff --git a/packages/hash-blob-browser/vitest.config.ts b/packages/hash-blob-browser/vitest.config.ts new file mode 100644 index 00000000000..44808064872 --- /dev/null +++ b/packages/hash-blob-browser/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/hash-node/jest.config.js b/packages/hash-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/hash-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/hash-node/package.json b/packages/hash-node/package.json index 2993d615831..33de6d98a69 100644 --- a/packages/hash-node/package.json +++ b/packages/hash-node/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/hash-node/src/index.spec.ts b/packages/hash-node/src/index.spec.ts index 3fa6f5152e5..fb45771d708 100644 --- a/packages/hash-node/src/index.spec.ts +++ b/packages/hash-node/src/index.spec.ts @@ -1,4 +1,5 @@ import { fromArrayBuffer, fromString } from "@smithy/util-buffer-from"; +import { describe, expect, test as it } from "vitest"; import { Hash } from "./"; const hashVectors = require("hash-test-vectors"); diff --git a/packages/hash-node/vitest.config.ts b/packages/hash-node/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/hash-node/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/hash-stream-node/jest.config.js b/packages/hash-stream-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/hash-stream-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/hash-stream-node/package.json b/packages/hash-stream-node/package.json index fe032c725a2..f00cf496bff 100644 --- a/packages/hash-stream-node/package.json +++ b/packages/hash-stream-node/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/hash-stream-node/src/HashCalculator.spec.ts b/packages/hash-stream-node/src/HashCalculator.spec.ts index 8cb0b3cc13c..415c833971d 100644 --- a/packages/hash-stream-node/src/HashCalculator.spec.ts +++ b/packages/hash-stream-node/src/HashCalculator.spec.ts @@ -1,4 +1,5 @@ import { toUint8Array } from "@smithy/util-utf8/src"; +import { describe, expect, test as it } from "vitest"; import { HashCalculator } from "./HashCalculator"; diff --git a/packages/hash-stream-node/src/fileStreamHasher.spec.ts b/packages/hash-stream-node/src/fileStreamHasher.spec.ts index a35dae50857..a82c3c4fb8c 100644 --- a/packages/hash-stream-node/src/fileStreamHasher.spec.ts +++ b/packages/hash-stream-node/src/fileStreamHasher.spec.ts @@ -4,6 +4,7 @@ import { createReadStream, mkdtempSync, writeFileSync } from "fs"; import { tmpdir } from "os"; import { join } from "path"; import { Readable } from "stream"; +import { describe, expect, test as it, vi } from "vitest"; import { fileStreamHasher } from "./fileStreamHasher"; @@ -30,8 +31,8 @@ describe("fileStreamHasher", () => { it("does not exhaust the input stream", async () => { const inputStream = createReadStream(temporaryFile); - const onSpy = jest.spyOn(inputStream, "on"); - const pipeSpy = jest.spyOn(inputStream, "pipe"); + const onSpy = vi.spyOn(inputStream, "on"); + const pipeSpy = vi.spyOn(inputStream, "pipe"); const result = await fileStreamHasher(Sha256, inputStream); diff --git a/packages/hash-stream-node/src/readableStreamHasher.spec.ts b/packages/hash-stream-node/src/readableStreamHasher.spec.ts index 57548cd3df6..aad64a8550f 100644 --- a/packages/hash-stream-node/src/readableStreamHasher.spec.ts +++ b/packages/hash-stream-node/src/readableStreamHasher.spec.ts @@ -1,20 +1,21 @@ import { Hash } from "@smithy/types"; import { Readable, Writable } from "stream"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { HashCalculator } from "./HashCalculator"; import { readableStreamHasher } from "./readableStreamHasher"; -jest.mock("./HashCalculator"); +vi.mock("./HashCalculator"); describe(readableStreamHasher.name, () => { - const mockDigest = jest.fn(); - const mockHashCtor = jest.fn().mockImplementation(() => ({ - update: jest.fn(), + const mockDigest = vi.fn(); + const mockHashCtor = vi.fn().mockImplementation(() => ({ + update: vi.fn(), digest: mockDigest, })); - const mockHashCalculatorWrite = jest.fn(); - const mockHashCalculatorEnd = jest.fn(); + const mockHashCalculatorWrite = vi.fn(); + const mockHashCalculatorEnd = vi.fn(); const mockHash = new Uint8Array(Buffer.from("mockHash")); @@ -39,14 +40,14 @@ describe(readableStreamHasher.name, () => { } beforeEach(() => { - (HashCalculator as unknown as jest.Mock).mockImplementation( + (HashCalculator as unknown as any).mockImplementation( (hash) => new MockHashCalculator(hash, mockHashCalculatorWrite, mockHashCalculatorEnd) ); mockDigest.mockResolvedValue(mockHash); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("computes hash for a readable stream", async () => { @@ -112,7 +113,7 @@ describe(readableStreamHasher.name, () => { mockHashCalculatorWrite, mockHashCalculatorEnd ); - (HashCalculator as unknown as jest.Mock).mockImplementation(() => mockHashCalculator); + (HashCalculator as unknown as any).mockImplementation(() => mockHashCalculator); const readableStream = new Readable({ read: () => {}, diff --git a/packages/hash-stream-node/vitest.config.ts b/packages/hash-stream-node/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/hash-stream-node/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/invalid-dependency/jest.config.js b/packages/invalid-dependency/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/invalid-dependency/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/invalid-dependency/package.json b/packages/invalid-dependency/package.json index cdba155b823..3303f3eca02 100644 --- a/packages/invalid-dependency/package.json +++ b/packages/invalid-dependency/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/invalid-dependency/src/invalidFunction.spec.ts b/packages/invalid-dependency/src/invalidFunction.spec.ts index d58782e7927..68f4e84cdc7 100644 --- a/packages/invalid-dependency/src/invalidFunction.spec.ts +++ b/packages/invalid-dependency/src/invalidFunction.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { invalidFunction } from "./invalidFunction"; describe("invalidFunction", () => { diff --git a/packages/invalid-dependency/src/invalidProvider.spec.ts b/packages/invalid-dependency/src/invalidProvider.spec.ts index 4b7d01a6bc1..72845b0aeb8 100644 --- a/packages/invalid-dependency/src/invalidProvider.spec.ts +++ b/packages/invalid-dependency/src/invalidProvider.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { invalidProvider } from "./invalidProvider"; describe("invalidProvider", () => { diff --git a/packages/invalid-dependency/vitest.config.ts b/packages/invalid-dependency/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/invalid-dependency/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/is-array-buffer/jest.config.js b/packages/is-array-buffer/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/is-array-buffer/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/is-array-buffer/package.json b/packages/is-array-buffer/package.json index bcbe06f4b22..ec06e13af3a 100644 --- a/packages/is-array-buffer/package.json +++ b/packages/is-array-buffer/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/is-array-buffer/src/index.spec.ts b/packages/is-array-buffer/src/index.spec.ts index 97986abed0e..82d04378518 100644 --- a/packages/is-array-buffer/src/index.spec.ts +++ b/packages/is-array-buffer/src/index.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { isArrayBuffer } from "./"; describe("isArrayBuffer", () => { @@ -26,7 +28,7 @@ describe("isArrayBuffer", () => { it("should return true for ArrayBuffers created with a different instance of the ArrayBuffer constructor", () => { const buffer = new ArrayBuffer(0); - (ArrayBuffer as any) = jest.fn(() => buffer); + (ArrayBuffer as any) = vi.fn(() => buffer); expect(buffer).not.toBeInstanceOf(ArrayBuffer); expect(isArrayBuffer(buffer)).toBe(true); diff --git a/packages/is-array-buffer/vitest.config.ts b/packages/is-array-buffer/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/is-array-buffer/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/md5-js/jest.config.js b/packages/md5-js/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/md5-js/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/md5-js/package.json b/packages/md5-js/package.json index 0ba3a2fc7fa..54ef4c237d0 100644 --- a/packages/md5-js/package.json +++ b/packages/md5-js/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/md5-js/src/index.spec.ts b/packages/md5-js/src/index.spec.ts index c4c427ec972..6e8aa2a091f 100644 --- a/packages/md5-js/src/index.spec.ts +++ b/packages/md5-js/src/index.spec.ts @@ -1,5 +1,6 @@ import { fromBase64 } from "@smithy/util-base64"; import { toHex } from "@smithy/util-hex-encoding"; +import { describe, expect, test as it } from "vitest"; import { Md5 } from "./"; const hashVectors = require("hash-test-vectors"); diff --git a/packages/md5-js/vitest.config.ts b/packages/md5-js/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/md5-js/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-apply-body-checksum/jest.config.integ.js b/packages/middleware-apply-body-checksum/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/middleware-apply-body-checksum/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/middleware-apply-body-checksum/jest.config.js b/packages/middleware-apply-body-checksum/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-apply-body-checksum/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-apply-body-checksum/package.json b/packages/middleware-apply-body-checksum/package.json index 6426e1b53c4..50bac4a38ef 100644 --- a/packages/middleware-apply-body-checksum/package.json +++ b/packages/middleware-apply-body-checksum/package.json @@ -11,8 +11,10 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --coverage", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test": "yarn g:vitest run", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-apply-body-checksum/src/applyMd5BodyChecksumMiddleware.spec.ts b/packages/middleware-apply-body-checksum/src/applyMd5BodyChecksumMiddleware.spec.ts index 68112ea2247..95b04cdbbe0 100644 --- a/packages/middleware-apply-body-checksum/src/applyMd5BodyChecksumMiddleware.spec.ts +++ b/packages/middleware-apply-body-checksum/src/applyMd5BodyChecksumMiddleware.spec.ts @@ -1,19 +1,20 @@ import { HttpRequest } from "@smithy/protocol-http"; import { ChecksumConstructor } from "@smithy/types"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { applyMd5BodyChecksumMiddleware } from "./applyMd5BodyChecksumMiddleware"; describe("applyMd5BodyChecksumMiddleware", () => { - const mockEncoder = jest.fn().mockReturnValue("encoded"); - const mockHashUpdate = jest.fn(); - const mockHashDigest = jest.fn().mockReturnValue(new Uint8Array(0)); - const mockHashReset = jest.fn(); + const mockEncoder = vi.fn().mockReturnValue("encoded"); + const mockHashUpdate = vi.fn(); + const mockHashDigest = vi.fn().mockReturnValue(new Uint8Array(0)); + const mockHashReset = vi.fn(); const MockHash: ChecksumConstructor = class {} as any; MockHash.prototype.update = mockHashUpdate; MockHash.prototype.digest = mockHashDigest; MockHash.prototype.reset = mockHashReset; - const next = jest.fn(); + const next = vi.fn(); class ExoticStream {} diff --git a/packages/middleware-apply-body-checksum/src/index.spec.ts b/packages/middleware-apply-body-checksum/src/index.spec.ts index 4195e575a30..ff1fb34342a 100644 --- a/packages/middleware-apply-body-checksum/src/index.spec.ts +++ b/packages/middleware-apply-body-checksum/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { applyMd5BodyChecksumMiddleware } from "./index"; describe("middleware-apply-body-checksum package exports", () => { diff --git a/packages/middleware-apply-body-checksum/src/middleware-apply-body-checksum.integ.spec.ts b/packages/middleware-apply-body-checksum/src/middleware-apply-body-checksum.integ.spec.ts index 552aa9e544b..449049e4894 100644 --- a/packages/middleware-apply-body-checksum/src/middleware-apply-body-checksum.integ.spec.ts +++ b/packages/middleware-apply-body-checksum/src/middleware-apply-body-checksum.integ.spec.ts @@ -1,6 +1,8 @@ -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, expect, test as it } from "vitest"; import { Weather } from "weather"; +import { requireRequestsFrom } from "../../../private/util-test/src/index"; + describe("middleware-apply-body-checksum", () => { describe(Weather.name, () => { it("should add body-checksum", async () => { diff --git a/packages/middleware-apply-body-checksum/vitest.config.integ.ts b/packages/middleware-apply-body-checksum/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/middleware-apply-body-checksum/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-apply-body-checksum/vitest.config.ts b/packages/middleware-apply-body-checksum/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/middleware-apply-body-checksum/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-compression/jest.config.js b/packages/middleware-compression/jest.config.js deleted file mode 100644 index 95d8863b22a..00000000000 --- a/packages/middleware-compression/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testMatch: ["**/*.spec.ts"], -}; diff --git a/packages/middleware-compression/package.json b/packages/middleware-compression/package.json index 5b4914fd9e3..c3de4f19a39 100644 --- a/packages/middleware-compression/package.json +++ b/packages/middleware-compression/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "rimraf dist-types/ts3.4 && downlevel-dts dist-types dist-types/ts3.4", "stage-release": "rimraf ./.release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-compression/src/NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS.spec.ts b/packages/middleware-compression/src/NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS.spec.ts index f859a259511..40be7973ae3 100644 --- a/packages/middleware-compression/src/NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS.spec.ts +++ b/packages/middleware-compression/src/NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS.spec.ts @@ -1,3 +1,5 @@ +import { test as it, vi, afterEach, describe, expect } from "vitest"; + import { booleanSelector, SelectorType } from "@smithy/util-config-provider"; import { @@ -7,23 +9,23 @@ import { NODE_DISABLE_REQUEST_COMPRESSION_INI_NAME, } from "./NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS"; -jest.mock("@smithy/util-config-provider"); +vi.mock("@smithy/util-config-provider"); describe("NODE_DISABLE_REQUEST_COMPRESSION_CONFIG_OPTIONS", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); const test = (func: Function, obj: Record, key: string, type: SelectorType) => { it.each([true, false, undefined])("returns %s", (output) => { - (booleanSelector as jest.Mock).mockReturnValueOnce(output); + (vi.mocked(booleanSelector)).mockReturnValueOnce(output); expect(func(obj)).toEqual(output); expect(booleanSelector).toBeCalledWith(obj, key, type); }); it("throws error", () => { const mockError = new Error("error"); - (booleanSelector as jest.Mock).mockImplementationOnce(() => { + (vi.mocked(booleanSelector)).mockImplementationOnce(() => { throw mockError; }); expect(() => { diff --git a/packages/middleware-compression/src/NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS.spec.ts b/packages/middleware-compression/src/NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS.spec.ts index 95bda3f70cc..7c8765122a4 100644 --- a/packages/middleware-compression/src/NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS.spec.ts +++ b/packages/middleware-compression/src/NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS.spec.ts @@ -1,3 +1,5 @@ +import { test as it, vi, afterEach, describe, expect } from "vitest"; + import { numberSelector, SelectorType } from "@smithy/util-config-provider"; import { @@ -7,23 +9,23 @@ import { NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_INI_NAME, } from "./NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS"; -jest.mock("@smithy/util-config-provider"); +vi.mock("@smithy/util-config-provider"); describe("NODE_REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_OPTIONS", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); const test = (func: Function, obj: Record, key: string, type: SelectorType) => { it.each([0, 1, undefined])("returns %s", (output) => { - (numberSelector as jest.Mock).mockReturnValueOnce(output); + (vi.mocked(numberSelector)).mockReturnValueOnce(output); expect(func(obj)).toEqual(output); expect(numberSelector).toBeCalledWith(obj, key, type); }); it("throws error", () => { const mockError = new Error("error"); - (numberSelector as jest.Mock).mockImplementationOnce(() => { + (vi.mocked(numberSelector)).mockImplementationOnce(() => { throw mockError; }); expect(() => { diff --git a/packages/middleware-compression/src/compressStream.browser.spec.ts b/packages/middleware-compression/src/compressStream.browser.spec.ts index bca22275e4c..aca381e9d95 100644 --- a/packages/middleware-compression/src/compressStream.browser.spec.ts +++ b/packages/middleware-compression/src/compressStream.browser.spec.ts @@ -1,28 +1,29 @@ -// @jest-environment jsdom +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { AsyncGzip } from "fflate"; import { ReadableStream } from "web-streams-polyfill"; import { compressStream } from "./compressStream.browser"; -jest.mock("fflate"); +vi.mock("fflate"); describe(compressStream.name, () => { const compressionSuffix = "compressed"; const compressionSeparator = "."; const asyncGzip = { - ondata: jest.fn(), - push: jest.fn().mockImplementation((chunk, final) => { + ondata: vi.fn(), + push: vi.fn().mockImplementation((chunk, final) => { const data = typeof chunk === "string" ? [chunk, compressionSuffix].join(compressionSeparator) : null; asyncGzip.ondata(undefined, data, final); }), }; beforeEach(() => { - (AsyncGzip as jest.Mock).mockImplementation(() => asyncGzip); + (vi.mocked(AsyncGzip)).mockImplementation(() => asyncGzip); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("compresses a stream", async () => { @@ -58,7 +59,7 @@ describe(compressStream.name, () => { it("should throw an error if compression fails", async () => { const compressionErrorMsg = "compression error message"; const compressionError = new Error(compressionErrorMsg); - (AsyncGzip as jest.Mock).mockImplementationOnce(() => { + (vi.mocked(AsyncGzip)).mockImplementationOnce(() => { throw compressionError; }); diff --git a/packages/middleware-compression/src/compressStream.spec.ts b/packages/middleware-compression/src/compressStream.spec.ts index 96ee325ca28..e9e9e02c06f 100644 --- a/packages/middleware-compression/src/compressStream.spec.ts +++ b/packages/middleware-compression/src/compressStream.spec.ts @@ -1,9 +1,11 @@ +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { Readable } from "stream"; import { createGzip } from "zlib"; import { compressStream } from "./compressStream"; -jest.mock("zlib"); +vi.mock("zlib"); describe(compressStream.name, () => { const getGenerator = (chunks: string[]) => @@ -14,16 +16,16 @@ describe(compressStream.name, () => { }; const testInputStream = Readable.from(getGenerator(["input"])()); - const mockGzipFn = jest.fn(); + const mockGzipFn = vi.fn(); const testOutputStream = Readable.from(getGenerator(["input", "gzipped"])()); beforeEach(() => { - (createGzip as jest.Mock).mockReturnValue(mockGzipFn); - testInputStream.pipe = jest.fn().mockReturnValue(testOutputStream); + (vi.mocked(createGzip)).mockReturnValue(mockGzipFn); + testInputStream.pipe = vi.fn().mockReturnValue(testOutputStream); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should compress a readable stream using gzip", async () => { @@ -40,7 +42,7 @@ describe(compressStream.name, () => { it("should throw an error if compression fails", async () => { const compressionErrorMsg = "compression error message"; const compressionError = new Error(compressionErrorMsg); - (createGzip as jest.Mock).mockImplementationOnce(() => { + (vi.mocked(createGzip)).mockImplementationOnce(() => { throw compressionError; }); diff --git a/packages/middleware-compression/src/compressString.browser.spec.ts b/packages/middleware-compression/src/compressString.browser.spec.ts index 0a03de31864..92b1ae1f22e 100644 --- a/packages/middleware-compression/src/compressString.browser.spec.ts +++ b/packages/middleware-compression/src/compressString.browser.spec.ts @@ -1,11 +1,12 @@ -// @jest-environment jsdom +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { toUint8Array } from "@smithy/util-utf8"; import { gzip } from "fflate"; import { compressString } from "./compressString.browser"; -jest.mock("@smithy/util-utf8"); -jest.mock("fflate"); +vi.mock("@smithy/util-utf8"); +vi.mock("fflate"); describe(compressString.name, () => { const testData = "test"; @@ -13,15 +14,15 @@ describe(compressString.name, () => { const compressionSeparator = "."; beforeEach(() => { - (toUint8Array as jest.Mock).mockImplementation((data) => data); + (vi.mocked(toUint8Array)).mockImplementation((data) => data); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should compress data with gzip", async () => { - (gzip as jest.Mock).mockImplementation((data, callback) => { + (vi.mocked(gzip)).mockImplementation((data, callback) => { callback(null, [data, compressionSuffix].join(compressionSeparator)); }); const receivedOutput = await compressString(testData); @@ -37,7 +38,7 @@ describe(compressString.name, () => { it("should throw an error if compression fails", async () => { const compressionErrorMsg = "compression error message"; const compressionError = new Error(compressionErrorMsg); - (gzip as jest.Mock).mockImplementation((data, callback) => { + (vi.mocked(gzip)).mockImplementation((data, callback) => { callback(compressionError); }); diff --git a/packages/middleware-compression/src/compressString.spec.ts b/packages/middleware-compression/src/compressString.spec.ts index ed7d2f80580..bdfe8838a6e 100644 --- a/packages/middleware-compression/src/compressString.spec.ts +++ b/packages/middleware-compression/src/compressString.spec.ts @@ -1,3 +1,5 @@ +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { toUint8Array } from "@smithy/util-utf8"; import { gzip } from "zlib"; @@ -6,21 +8,21 @@ import { compressString } from "./compressString"; const compressionSuffix = "compressed"; const compressionSeparator = "."; -jest.mock("@smithy/util-utf8"); -jest.mock("util", () => ({ promisify: jest.fn().mockImplementation((fn) => fn) })); -jest.mock("zlib", () => ({ - gzip: jest.fn().mockImplementation((data) => [data, compressionSuffix].join(compressionSeparator)), +vi.mock("@smithy/util-utf8"); +vi.mock("util", () => ({ promisify: vi.fn().mockImplementation((fn) => fn) })); +vi.mock("zlib", () => ({ + gzip: vi.fn().mockImplementation((data) => [data, compressionSuffix].join(compressionSeparator)), })); describe(compressString.name, () => { const testData = "test"; beforeEach(() => { - (toUint8Array as jest.Mock).mockImplementation((data) => data); + (vi.mocked(toUint8Array)).mockImplementation((data) => data); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should compress data with gzip", async () => { @@ -38,7 +40,7 @@ describe(compressString.name, () => { it("should throw an error if compression fails", async () => { const compressionErrorMsg = "compression error message"; const compressionError = new Error(compressionErrorMsg); - ((gzip as unknown) as jest.Mock).mockImplementationOnce(() => { + ((gzip as unknown) as any).mockImplementationOnce(() => { throw compressionError; }); diff --git a/packages/middleware-compression/src/compressionMiddleware.spec.ts b/packages/middleware-compression/src/compressionMiddleware.spec.ts index 95d9099748e..99f925f1163 100644 --- a/packages/middleware-compression/src/compressionMiddleware.spec.ts +++ b/packages/middleware-compression/src/compressionMiddleware.spec.ts @@ -1,3 +1,5 @@ +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { HttpRequest } from "@smithy/protocol-http"; import { compressionMiddleware } from "./compressionMiddleware"; @@ -6,15 +8,15 @@ import { compressString } from "./compressString"; import { CompressionAlgorithm } from "./constants"; import { isStreaming } from "./isStreaming"; -jest.mock("@smithy/protocol-http"); -jest.mock("./compressString"); -jest.mock("./compressStream"); -jest.mock("./isStreaming"); +vi.mock("@smithy/protocol-http"); +vi.mock("./compressString"); +vi.mock("./compressStream"); +vi.mock("./isStreaming"); describe(compressionMiddleware.name, () => { const mockBody = "body"; const mockConfig = { - bodyLengthChecker: jest.fn().mockReturnValue(mockBody.length), + bodyLengthChecker: vi.fn().mockReturnValue(mockBody.length), disableRequestCompression: async () => false, requestMinCompressionSizeBytes: async () => 0, }; @@ -22,17 +24,17 @@ describe(compressionMiddleware.name, () => { encodings: [CompressionAlgorithm.GZIP], }; - const mockNext = jest.fn(); + const mockNext = vi.fn(); const mockContext = {}; const mockArgs = { request: { headers: {}, body: mockBody } }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("skips compression if it's not an HttpRequest", async () => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); await compressionMiddleware(mockConfig, mockMiddlewareConfig)(mockNext, mockContext)({ ...mockArgs } as any); expect(mockNext).toHaveBeenCalledWith(mockArgs); }); @@ -40,8 +42,8 @@ describe(compressionMiddleware.name, () => { describe("HttpRequest", () => { beforeEach(() => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); - (isStreaming as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(true); + (vi.mocked(isStreaming)).mockReturnValue(false); }); it("skips compression if disabled", async () => { @@ -64,7 +66,7 @@ describe(compressionMiddleware.name, () => { describe("streaming", () => { beforeEach(() => { - (isStreaming as jest.Mock).mockReturnValue(true); + (vi.mocked(isStreaming)).mockReturnValue(true); }); it("throws error if streaming blob requires length", async () => { @@ -82,7 +84,7 @@ describe(compressionMiddleware.name, () => { it("compresses streaming blob", async () => { const mockCompressedStream = "compressed-stream"; - (compressStream as jest.Mock).mockResolvedValueOnce(mockCompressedStream); + (vi.mocked(compressStream)).mockResolvedValueOnce(mockCompressedStream); await compressionMiddleware(mockConfig, mockMiddlewareConfig)(mockNext, mockContext)({ ...mockArgs } as any); @@ -119,7 +121,7 @@ describe(compressionMiddleware.name, () => { it("compresses body", async () => { const mockCompressedBody = "compressed-body"; - (compressString as jest.Mock).mockResolvedValueOnce(mockCompressedBody); + (vi.mocked(compressString)).mockResolvedValueOnce(mockCompressedBody); await compressionMiddleware(mockConfig, mockMiddlewareConfig)(mockNext, mockContext)({ ...mockArgs } as any); @@ -140,7 +142,7 @@ describe(compressionMiddleware.name, () => { it("appends algorithm to existing Content-Encoding header", async () => { const mockCompressedBody = "compressed-body"; - (compressString as jest.Mock).mockResolvedValueOnce(mockCompressedBody); + (vi.mocked(compressString)).mockResolvedValueOnce(mockCompressedBody); const mockExistingContentEncoding = "deflate"; await compressionMiddleware(mockConfig, mockMiddlewareConfig)(mockNext, mockContext)({ diff --git a/packages/middleware-compression/src/getCompressionPlugin.spec.ts b/packages/middleware-compression/src/getCompressionPlugin.spec.ts index 969bbf5bb24..b1c3f04b192 100644 --- a/packages/middleware-compression/src/getCompressionPlugin.spec.ts +++ b/packages/middleware-compression/src/getCompressionPlugin.spec.ts @@ -1,11 +1,13 @@ +import { test as it, vi, describe, expect } from "vitest"; + import { compressionMiddleware, compressionMiddlewareOptions } from "./compressionMiddleware"; import { getCompressionPlugin } from "./getCompressionPlugin"; -jest.mock("./compressionMiddleware"); +vi.mock("./compressionMiddleware"); describe(getCompressionPlugin.name, () => { const config = { - bodyLengthChecker: jest.fn(), + bodyLengthChecker: vi.fn(), disableRequestCompression: async () => false, requestMinCompressionSizeBytes: async () => 0, }; @@ -13,10 +15,10 @@ describe(getCompressionPlugin.name, () => { it("applyToStack adds compressionMiddleware", () => { const middlewareReturn = {}; - (compressionMiddleware as jest.Mock).mockReturnValueOnce(middlewareReturn); + (vi.mocked(compressionMiddleware)).mockReturnValueOnce(middlewareReturn); const plugin = getCompressionPlugin(config, middlewareConfig); - const commandStack = { add: jest.fn() }; + const commandStack = { add: vi.fn() }; // @ts-ignore plugin.applyToStack(commandStack); diff --git a/packages/middleware-compression/src/isStreaming.spec.ts b/packages/middleware-compression/src/isStreaming.spec.ts index 8da1f3ba478..b71dd0c940b 100644 --- a/packages/middleware-compression/src/isStreaming.spec.ts +++ b/packages/middleware-compression/src/isStreaming.spec.ts @@ -1,20 +1,22 @@ +import { test as it, vi, beforeEach, afterEach, describe, expect } from "vitest"; + import { isArrayBuffer } from "@smithy/is-array-buffer"; import { isStreaming } from "./isStreaming"; -jest.mock("@smithy/is-array-buffer"); +vi.mock("@smithy/is-array-buffer"); describe(isStreaming.name, () => { beforeEach(() => { - ((isArrayBuffer as unknown) as jest.Mock).mockReturnValue(true); + ((isArrayBuffer as unknown) as any).mockReturnValue(true); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns true when body is a stream", () => { - ((isArrayBuffer as unknown) as jest.Mock).mockReturnValue(false); + ((isArrayBuffer as unknown) as any).mockReturnValue(false); // Mocking {} as a stream const mockStream = {}; expect(isStreaming(mockStream)).toBe(true); diff --git a/packages/middleware-compression/src/resolveCompressionConfig.spec.ts b/packages/middleware-compression/src/resolveCompressionConfig.spec.ts index a2e78860173..db62bd4a61b 100644 --- a/packages/middleware-compression/src/resolveCompressionConfig.spec.ts +++ b/packages/middleware-compression/src/resolveCompressionConfig.spec.ts @@ -1,8 +1,10 @@ +import { test as it, vi, describe, expect } from "vitest"; + import { resolveCompressionConfig } from "./resolveCompressionConfig"; describe(resolveCompressionConfig.name, () => { const mockConfig = { - bodyLengthChecker: jest.fn(), + bodyLengthChecker: vi.fn(), disableRequestCompression: false, requestMinCompressionSizeBytes: 0, }; diff --git a/packages/middleware-compression/vitest.config.ts b/packages/middleware-compression/vitest.config.ts new file mode 100644 index 00000000000..9025ae49f3f --- /dev/null +++ b/packages/middleware-compression/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "vitest/config"; + + export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + + }, + }); + \ No newline at end of file diff --git a/packages/middleware-content-length/jest.config.integ.js b/packages/middleware-content-length/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/middleware-content-length/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/middleware-content-length/jest.config.js b/packages/middleware-content-length/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-content-length/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-content-length/package.json b/packages/middleware-content-length/package.json index 9541a0a1244..f806b5c4829 100644 --- a/packages/middleware-content-length/package.json +++ b/packages/middleware-content-length/package.json @@ -12,7 +12,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "test": "exit 0", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-content-length/src/middleware-content-length.integ.spec.ts b/packages/middleware-content-length/src/middleware-content-length.integ.spec.ts index b0e4242ae1e..f5ccc2b0bf7 100644 --- a/packages/middleware-content-length/src/middleware-content-length.integ.spec.ts +++ b/packages/middleware-content-length/src/middleware-content-length.integ.spec.ts @@ -1,6 +1,8 @@ -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, expect, test as it } from "vitest"; import { Weather } from "weather"; +import { requireRequestsFrom } from "../../../private/util-test/src/index"; + describe("middleware-content-length", () => { describe(Weather.name, () => { it("should not add content-length if no body", async () => { diff --git a/packages/middleware-content-length/vitest.config.integ.ts b/packages/middleware-content-length/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/middleware-content-length/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-endpoint/jest.config.integ.js b/packages/middleware-endpoint/jest.config.integ.js deleted file mode 100644 index d09aba7398c..00000000000 --- a/packages/middleware-endpoint/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/middleware-endpoint/jest.config.js b/packages/middleware-endpoint/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-endpoint/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-endpoint/package.json b/packages/middleware-endpoint/package.json index 0c75cb7dc98..1dd985f93d9 100644 --- a/packages/middleware-endpoint/package.json +++ b/packages/middleware-endpoint/package.json @@ -11,8 +11,9 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --passWithNoTests", - "extract:docs": "api-extractor run --local" + "test": "yarn g:vitest run", + "extract:docs": "api-extractor run --local", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-endpoint/src/adaptors/createConfigValueProvider.spec.ts b/packages/middleware-endpoint/src/adaptors/createConfigValueProvider.spec.ts index 5ec1674a2ef..e34401d1876 100644 --- a/packages/middleware-endpoint/src/adaptors/createConfigValueProvider.spec.ts +++ b/packages/middleware-endpoint/src/adaptors/createConfigValueProvider.spec.ts @@ -1,4 +1,5 @@ import { Endpoint } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { createConfigValueProvider } from "./createConfigValueProvider"; diff --git a/packages/middleware-endpoint/src/adaptors/getEndpointUrlConfig.spec.ts b/packages/middleware-endpoint/src/adaptors/getEndpointUrlConfig.spec.ts index cf69f78f759..61e679fb76a 100644 --- a/packages/middleware-endpoint/src/adaptors/getEndpointUrlConfig.spec.ts +++ b/packages/middleware-endpoint/src/adaptors/getEndpointUrlConfig.spec.ts @@ -1,4 +1,5 @@ import { CONFIG_PREFIX_SEPARATOR } from "@smithy/shared-ini-file-loader"; +import { afterEach, beforeEach, describe, expect, test as it } from "vitest"; import { getEndpointUrlConfig } from "./getEndpointUrlConfig"; diff --git a/packages/middleware-endpoint/src/service-customizations/s3.spec.ts b/packages/middleware-endpoint/src/service-customizations/s3.spec.ts index 2eacfbac80a..36e06c477cd 100644 --- a/packages/middleware-endpoint/src/service-customizations/s3.spec.ts +++ b/packages/middleware-endpoint/src/service-customizations/s3.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isArnBucketName } from "./s3"; describe("S3 customizations for endpoint resolution", () => { diff --git a/packages/middleware-endpoint/vitest.config.ts b/packages/middleware-endpoint/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/middleware-endpoint/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-retry/jest.config.integ.js b/packages/middleware-retry/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/middleware-retry/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/middleware-retry/jest.config.js b/packages/middleware-retry/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-retry/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-retry/package.json b/packages/middleware-retry/package.json index 2286a3730d1..a305f124a8f 100644 --- a/packages/middleware-retry/package.json +++ b/packages/middleware-retry/package.json @@ -12,8 +12,10 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test": "yarn g:vitest run", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-retry/src/AdaptiveRetryStrategy.spec.ts b/packages/middleware-retry/src/AdaptiveRetryStrategy.spec.ts index bde51f3c9bd..0e0a7e94ed9 100644 --- a/packages/middleware-retry/src/AdaptiveRetryStrategy.spec.ts +++ b/packages/middleware-retry/src/AdaptiveRetryStrategy.spec.ts @@ -1,31 +1,32 @@ import { DefaultRateLimiter, RateLimiter, RETRY_MODES } from "@smithy/util-retry"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { AdaptiveRetryStrategy } from "./AdaptiveRetryStrategy"; import { StandardRetryStrategy } from "./StandardRetryStrategy"; import { RetryQuota } from "./types"; -jest.mock("./StandardRetryStrategy"); -jest.mock("@smithy/util-retry"); +vi.mock("./StandardRetryStrategy"); +vi.mock("@smithy/util-retry"); describe(AdaptiveRetryStrategy.name, () => { - const maxAttemptsProvider = jest.fn(); + const maxAttemptsProvider = vi.fn(); const mockDefaultRateLimiter = { - getSendToken: jest.fn(), - updateClientSendingRate: jest.fn(), + getSendToken: vi.fn(), + updateClientSendingRate: vi.fn(), }; beforeEach(() => { - (DefaultRateLimiter as jest.Mock).mockReturnValue(mockDefaultRateLimiter); + vi.mocked(DefaultRateLimiter).mockReturnValue(mockDefaultRateLimiter); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("constructor", () => { it("calls super constructor", () => { - const retryDecider = jest.fn(); - const delayDecider = jest.fn(); + const retryDecider = vi.fn(); + const delayDecider = vi.fn(); const retryQuota = {} as RetryQuota; const rateLimiter = {} as RateLimiter; @@ -69,17 +70,17 @@ describe(AdaptiveRetryStrategy.name, () => { }); describe("retry", () => { - const mockedSuperRetry = jest.spyOn(StandardRetryStrategy.prototype, "retry"); + const mockedSuperRetry = vi.spyOn(StandardRetryStrategy.prototype, "retry"); beforeEach(async () => { - const next = jest.fn(); + const next = vi.fn(); const retryStrategy = new AdaptiveRetryStrategy(maxAttemptsProvider); await retryStrategy.retry(next, { request: { headers: {} } } as any); expect(mockedSuperRetry).toHaveBeenCalledTimes(1); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("calls rateLimiter.getSendToken in beforeRequest", async () => { diff --git a/packages/middleware-retry/src/StandardRetryStrategy.spec.ts b/packages/middleware-retry/src/StandardRetryStrategy.spec.ts index ad63a672f17..b317220b88c 100644 --- a/packages/middleware-retry/src/StandardRetryStrategy.spec.ts +++ b/packages/middleware-retry/src/StandardRetryStrategy.spec.ts @@ -8,6 +8,7 @@ import { THROTTLING_RETRY_DELAY_BASE, } from "@smithy/util-retry"; import { v4 } from "uuid"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getDefaultRetryQuota } from "./defaultRetryQuota"; import { defaultDelayDecider } from "./delayDecider"; @@ -15,25 +16,25 @@ import { defaultRetryDecider } from "./retryDecider"; import { StandardRetryStrategy } from "./StandardRetryStrategy"; import { RetryQuota } from "./types"; -jest.mock("@smithy/service-error-classification"); -jest.mock("./delayDecider"); -jest.mock("./retryDecider"); -jest.mock("./defaultRetryQuota"); -jest.mock("@smithy/protocol-http"); -jest.mock("uuid"); +vi.mock("@smithy/service-error-classification"); +vi.mock("./delayDecider"); +vi.mock("./retryDecider"); +vi.mock("./defaultRetryQuota"); +vi.mock("@smithy/protocol-http"); +vi.mock("uuid"); describe("defaultStrategy", () => { - let next: jest.Mock; // variable for next mock function in utility methods + let next: any; // variable for next mock function in utility methods const maxAttempts = 3; const mockDefaultRetryQuota = { - hasRetryTokens: jest.fn().mockReturnValue(true), - retrieveRetryTokens: jest.fn().mockReturnValue(1), - releaseRetryTokens: jest.fn(), + hasRetryTokens: vi.fn().mockReturnValue(true), + retrieveRetryTokens: vi.fn().mockReturnValue(1), + releaseRetryTokens: vi.fn(), }; const mockSuccessfulOperation = (maxAttempts: number, options?: { mockResponse?: string }) => { - next = jest.fn().mockResolvedValueOnce({ + next = vi.fn().mockResolvedValueOnce({ response: options?.mockResponse, output: { $metadata: {} }, }); @@ -44,7 +45,7 @@ describe("defaultStrategy", () => { const mockFailedOperation = async (maxAttempts: number, options?: { mockError?: Error }) => { const mockError = options?.mockError ?? new Error("mockError"); - next = jest.fn().mockRejectedValue(mockError); + next = vi.fn().mockRejectedValue(mockError); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts)); try { @@ -62,7 +63,7 @@ describe("defaultStrategy", () => { output: { $metadata: {} }, }; - next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockResponse); + next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockResponse); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts)); return retryStrategy.retry(next, { request: { headers: {} } } as any); @@ -75,7 +76,7 @@ describe("defaultStrategy", () => { output: { $metadata: {} }, }; - next = jest + next = vi .fn() .mockRejectedValueOnce(mockError) .mockRejectedValueOnce(mockError) @@ -86,21 +87,21 @@ describe("defaultStrategy", () => { }; beforeEach(() => { - (isThrottlingError as jest.Mock).mockReturnValue(true); - (defaultDelayDecider as jest.Mock).mockReturnValue(0); - (defaultRetryDecider as jest.Mock).mockReturnValue(true); - (getDefaultRetryQuota as jest.Mock).mockReturnValue(mockDefaultRetryQuota); - (HttpRequest as unknown as jest.Mock).mockReturnValue({ - isInstance: jest.fn().mockReturnValue(false), + vi.mocked(isThrottlingError).mockReturnValue(true); + vi.mocked(defaultDelayDecider).mockReturnValue(0); + vi.mocked(defaultRetryDecider).mockReturnValue(true); + vi.mocked(getDefaultRetryQuota).mockReturnValue(mockDefaultRetryQuota); + (HttpRequest as unknown as any).mockReturnValue({ + isInstance: vi.fn().mockReturnValue(false), }); - (HttpResponse as unknown as jest.Mock).mockReturnValue({ - isInstance: jest.fn().mockReturnValue(false), + (HttpResponse as unknown as any).mockReturnValue({ + isInstance: vi.fn().mockReturnValue(false), }); - (v4 as jest.Mock).mockReturnValue("42"); + vi.mocked(v4).mockReturnValue("42"); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("sets maxAttemptsProvider as class member variable", () => { @@ -120,7 +121,7 @@ describe("defaultStrategy", () => { const maxAttempts = 1; const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts)); for (const error of nonStandardErrors) { - next = jest.fn().mockRejectedValue(error); + next = vi.fn().mockRejectedValue(error); expect(retryStrategy.retry(next, { request: { headers: {} } } as any)).rejects.toBeInstanceOf(Error); } }); @@ -137,7 +138,7 @@ describe("defaultStrategy", () => { }); it("sets options.retryDecider if defined", () => { - const retryDecider = jest.fn(); + const retryDecider = vi.fn(); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts), { retryDecider, }); @@ -157,7 +158,7 @@ describe("defaultStrategy", () => { }); it("sets options.delayDecider if defined", () => { - const delayDecider = jest.fn(); + const delayDecider = vi.fn(); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts), { delayDecider, }); @@ -188,15 +189,15 @@ describe("defaultStrategy", () => { describe("delayDecider", () => { describe("delayBase value passed", () => { const testDelayBasePassed = async (delayBaseToTest: number, mockThrottlingError: boolean) => { - (isThrottlingError as jest.Mock).mockReturnValueOnce(mockThrottlingError); + vi.mocked(isThrottlingError).mockReturnValueOnce(mockThrottlingError); const mockError = new Error(); await mockSuccessAfterOneFail(maxAttempts, { mockError }); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledWith(mockError); - expect(defaultDelayDecider as jest.Mock).toHaveBeenCalledTimes(1); - expect((defaultDelayDecider as jest.Mock).mock.calls[0][0]).toBe(delayBaseToTest); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledWith(mockError); + expect(vi.mocked(defaultDelayDecider)).toHaveBeenCalledTimes(1); + expect(vi.mocked(defaultDelayDecider).mock.calls[0][0]).toBe(delayBaseToTest); }; it("should be equal to THROTTLING_RETRY_DELAY_BASE if error is throttling error", async () => { @@ -211,41 +212,41 @@ describe("defaultStrategy", () => { describe("attempts value passed", () => { it("on successful operation", async () => { await mockSuccessfulOperation(maxAttempts); - expect(defaultDelayDecider as jest.Mock).not.toHaveBeenCalled(); + expect(vi.mocked(defaultDelayDecider)).not.toHaveBeenCalled(); }); it("in case of single failure", async () => { await mockSuccessAfterOneFail(maxAttempts); - expect(defaultDelayDecider as jest.Mock).toHaveBeenCalledTimes(1); - expect((defaultDelayDecider as jest.Mock).mock.calls[0][1]).toBe(1); + expect(vi.mocked(defaultDelayDecider)).toHaveBeenCalledTimes(1); + expect(vi.mocked(defaultDelayDecider).mock.calls[0][1]).toBe(1); }); it("on all fails", async () => { await mockFailedOperation(maxAttempts); - expect(defaultDelayDecider as jest.Mock).toHaveBeenCalledTimes(2); - expect((defaultDelayDecider as jest.Mock).mock.calls[0][1]).toBe(1); - expect((defaultDelayDecider as jest.Mock).mock.calls[1][1]).toBe(2); + expect(vi.mocked(defaultDelayDecider)).toHaveBeenCalledTimes(2); + expect(vi.mocked(defaultDelayDecider).mock.calls[0][1]).toBe(1); + expect(vi.mocked(defaultDelayDecider).mock.calls[1][1]).toBe(2); }); }); describe("totalRetryDelay", () => { describe("when retry-after is not set", () => { it("should be equal to sum of values computed by delayDecider", async () => { - jest.spyOn(global, "setTimeout"); + vi.spyOn(global, "setTimeout"); const FIRST_DELAY = 100; const SECOND_DELAY = 200; - (defaultDelayDecider as jest.Mock).mockReturnValueOnce(FIRST_DELAY).mockReturnValueOnce(SECOND_DELAY); + vi.mocked(defaultDelayDecider).mockReturnValueOnce(FIRST_DELAY).mockReturnValueOnce(SECOND_DELAY); const maxAttempts = 3; const error = await mockFailedOperation(maxAttempts); expect(error.$metadata.totalRetryDelay).toEqual(FIRST_DELAY + SECOND_DELAY); - expect(defaultDelayDecider as jest.Mock).toHaveBeenCalledTimes(maxAttempts - 1); + expect(vi.mocked(defaultDelayDecider)).toHaveBeenCalledTimes(maxAttempts - 1); expect(setTimeout).toHaveBeenCalledTimes(maxAttempts - 1); - expect((setTimeout as unknown as jest.Mock).mock.calls[0][1]).toBe(FIRST_DELAY); - expect((setTimeout as unknown as jest.Mock).mock.calls[1][1]).toBe(SECOND_DELAY); + expect((setTimeout as unknown as any).mock.calls[0][1]).toBe(FIRST_DELAY); + expect((setTimeout as unknown as any).mock.calls[1][1]).toBe(SECOND_DELAY); }); }); @@ -255,7 +256,7 @@ describe("defaultStrategy", () => { retryAfter: number | string, retryAfterHeaderName?: string ) => { - (defaultDelayDecider as jest.Mock).mockReturnValueOnce(delayDeciderInMs); + vi.mocked(defaultDelayDecider).mockReturnValueOnce(delayDeciderInMs); const maxAttempts = 2; const mockError = new Error(); @@ -265,20 +266,20 @@ describe("defaultStrategy", () => { }, }); const error = await mockFailedOperation(maxAttempts, { mockError }); - expect(defaultDelayDecider as jest.Mock).toHaveBeenCalledTimes(maxAttempts - 1); + expect(vi.mocked(defaultDelayDecider)).toHaveBeenCalledTimes(maxAttempts - 1); expect(setTimeout).toHaveBeenCalledTimes(maxAttempts - 1); return error; }; beforeEach(() => { - jest.spyOn(global, "setTimeout"); + vi.spyOn(global, "setTimeout"); }); describe("uses retry-after value if it's greater than that from delayDecider", () => { beforeEach(() => { const { isInstance } = HttpResponse; - (isInstance as unknown as jest.Mock).mockReturnValueOnce(true); + (isInstance as unknown as any).mockReturnValueOnce(true); }); describe("when value is in seconds", () => { @@ -288,7 +289,7 @@ describe("defaultStrategy", () => { const error = await getErrorWithValues(delayDeciderInMs, retryAfterInSeconds, retryAfterHeaderName); expect(error.$metadata.totalRetryDelay).toEqual(retryAfterInSeconds * 1000); - expect((setTimeout as unknown as jest.Mock).mock.calls[0][1]).toBe(retryAfterInSeconds * 1000); + expect((setTimeout as unknown as any).mock.calls[0][1]).toBe(retryAfterInSeconds * 1000); }; it("with header in small case", async () => { @@ -302,7 +303,7 @@ describe("defaultStrategy", () => { it("when value is a Date", async () => { const mockDateNow = Date.now(); - jest.spyOn(Date, "now").mockReturnValue(mockDateNow); + vi.spyOn(Date, "now").mockReturnValue(mockDateNow); const delayDeciderInMs = 2000; const retryAfterInSeconds = 3; @@ -310,7 +311,7 @@ describe("defaultStrategy", () => { const error = await getErrorWithValues(delayDeciderInMs, retryAfterDate.toISOString()); expect(error.$metadata.totalRetryDelay).toEqual(retryAfterInSeconds * 1000); - expect((setTimeout as unknown as jest.Mock).mock.calls[0][1]).toBe(retryAfterInSeconds * 1000); + expect((setTimeout as unknown as any).mock.calls[0][1]).toBe(retryAfterInSeconds * 1000); }); }); @@ -320,7 +321,7 @@ describe("defaultStrategy", () => { const error = await getErrorWithValues(delayDeciderInMs, retryAfterInSeconds); expect(error.$metadata.totalRetryDelay).toEqual(delayDeciderInMs); - expect((setTimeout as unknown as jest.Mock).mock.calls[0][1]).toBe(delayDeciderInMs); + expect((setTimeout as unknown as any).mock.calls[0][1]).toBe(delayDeciderInMs); }); }); }); @@ -358,7 +359,7 @@ describe("defaultStrategy", () => { it("called once with retryTokenAmount in case of single failure", async () => { const retryTokens = 15; const { releaseRetryTokens, retrieveRetryTokens } = getDefaultRetryQuota(INITIAL_RETRY_TOKENS); - (retrieveRetryTokens as jest.Mock).mockReturnValueOnce(retryTokens); + vi.mocked(retrieveRetryTokens).mockReturnValueOnce(retryTokens); await mockSuccessAfterOneFail(maxAttempts); expect(releaseRetryTokens).toHaveBeenCalledTimes(1); @@ -371,7 +372,7 @@ describe("defaultStrategy", () => { const { releaseRetryTokens, retrieveRetryTokens } = getDefaultRetryQuota(INITIAL_RETRY_TOKENS); - (retrieveRetryTokens as jest.Mock).mockReturnValueOnce(retryTokensFirst).mockReturnValueOnce(retryTokensSecond); + vi.mocked(retrieveRetryTokens).mockReturnValueOnce(retryTokensFirst).mockReturnValueOnce(retryTokensSecond); await mockSuccessAfterTwoFails(maxAttempts); expect(releaseRetryTokens).toHaveBeenCalledTimes(1); @@ -416,27 +417,27 @@ describe("defaultStrategy", () => { expect(response).toStrictEqual(mockResponse); expect(output.$metadata.attempts).toBe(1); expect(output.$metadata.totalRetryDelay).toBe(0); - expect(defaultRetryDecider as jest.Mock).not.toHaveBeenCalled(); - expect(defaultDelayDecider as jest.Mock).not.toHaveBeenCalled(); + expect(vi.mocked(defaultRetryDecider)).not.toHaveBeenCalled(); + expect(vi.mocked(defaultDelayDecider)).not.toHaveBeenCalled(); }); it("when retryDecider returns false", async () => { - (defaultRetryDecider as jest.Mock).mockReturnValueOnce(false); + vi.mocked(defaultRetryDecider).mockReturnValueOnce(false); const mockError = new Error(); await mockFailedOperation(maxAttempts, { mockError }); - expect(defaultRetryDecider as jest.Mock).toHaveBeenCalledTimes(1); - expect(defaultRetryDecider as jest.Mock).toHaveBeenCalledWith(mockError); + expect(vi.mocked(defaultRetryDecider)).toHaveBeenCalledTimes(1); + expect(vi.mocked(defaultRetryDecider)).toHaveBeenCalledWith(mockError); }); it("when the maximum number of attempts is reached", async () => { await mockFailedOperation(maxAttempts); - expect(defaultRetryDecider as jest.Mock).toHaveBeenCalledTimes(maxAttempts - 1); + expect(vi.mocked(defaultRetryDecider)).toHaveBeenCalledTimes(maxAttempts - 1); }); describe("when retryQuota.hasRetryTokens returns false", () => { it("in the first request", async () => { const { hasRetryTokens, retrieveRetryTokens, releaseRetryTokens } = getDefaultRetryQuota(INITIAL_RETRY_TOKENS); - (hasRetryTokens as jest.Mock).mockReturnValueOnce(false); + vi.mocked(hasRetryTokens).mockReturnValueOnce(false); const mockError = new Error(); await mockFailedOperation(maxAttempts, { mockError }); @@ -449,7 +450,7 @@ describe("defaultStrategy", () => { it("after the first retry", async () => { const { hasRetryTokens, retrieveRetryTokens, releaseRetryTokens } = getDefaultRetryQuota(INITIAL_RETRY_TOKENS); - (hasRetryTokens as jest.Mock).mockReturnValueOnce(true).mockReturnValueOnce(false); + vi.mocked(hasRetryTokens).mockReturnValueOnce(true).mockReturnValueOnce(false); const mockError = new Error(); await mockFailedOperation(maxAttempts, { mockError }); @@ -492,13 +493,13 @@ describe("defaultStrategy", () => { it("uses a unique header for every SDK operation invocation", async () => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); + (isInstance as unknown as any).mockReturnValue(true); const uuidForInvocationOne = "uuid-invocation-1"; const uuidForInvocationTwo = "uuid-invocation-2"; - (v4 as jest.Mock).mockReturnValueOnce(uuidForInvocationOne).mockReturnValueOnce(uuidForInvocationTwo); + vi.mocked(v4).mockReturnValueOnce(uuidForInvocationOne).mockReturnValueOnce(uuidForInvocationTwo); - const next = jest.fn().mockResolvedValue({ + const next = vi.fn().mockResolvedValue({ response: "mockResponse", output: { $metadata: {} }, }); @@ -511,15 +512,15 @@ describe("defaultStrategy", () => { expect(next.mock.calls[0][0].request.headers["amz-sdk-invocation-id"]).toBe(uuidForInvocationOne); expect(next.mock.calls[1][0].request.headers["amz-sdk-invocation-id"]).toBe(uuidForInvocationTwo); - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); }); it("uses same value for additional HTTP requests associated with an SDK operation", async () => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValueOnce(true); + (isInstance as unknown as any).mockReturnValueOnce(true); const uuidForInvocation = "uuid-invocation-1"; - (v4 as jest.Mock).mockReturnValueOnce(uuidForInvocation); + vi.mocked(v4).mockReturnValueOnce(uuidForInvocation); await mockSuccessAfterOneFail(maxAttempts); @@ -527,7 +528,7 @@ describe("defaultStrategy", () => { expect(next.mock.calls[0][0].request.headers["amz-sdk-invocation-id"]).toBe(uuidForInvocation); expect(next.mock.calls[1][0].request.headers["amz-sdk-invocation-id"]).toBe(uuidForInvocation); - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); }); }); @@ -558,12 +559,12 @@ describe("defaultStrategy", () => { it("adds header for each attempt", async () => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); + (isInstance as unknown as any).mockReturnValue(true); const mockError = new Error("mockError"); - next = jest.fn((args) => { - // the header needs to be verified inside jest.Mock as arguments in - // jest.mocks.calls has the value passed in final call + next = vi.fn((args) => { + // the header needs to be verified inside vi.Mock as arguments in + // vi.mocks.calls has the value passed in final call const index = next.mock.calls.length - 1; expect(args.request.headers["amz-sdk-request"]).toBe(`attempt=${index + 1}; max=${maxAttempts}`); throw mockError; @@ -578,16 +579,16 @@ describe("defaultStrategy", () => { } expect(next).toHaveBeenCalledTimes(maxAttempts); - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); }); }); describe("defaults maxAttempts to DEFAULT_MAX_ATTEMPTS", () => { it("when maxAttemptsProvider throws error", async () => { const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); + (isInstance as unknown as any).mockReturnValue(true); - next = jest.fn((args) => { + next = vi.fn((args) => { expect(args.request.headers["amz-sdk-request"]).toBe(`attempt=1; max=${DEFAULT_MAX_ATTEMPTS}`); return Promise.resolve({ response: "mockResponse", @@ -599,7 +600,7 @@ describe("defaultStrategy", () => { await retryStrategy.retry(next, { request: { headers: {} } } as any); expect(next).toHaveBeenCalledTimes(1); - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); }); }); }); diff --git a/packages/middleware-retry/src/configurations.spec.ts b/packages/middleware-retry/src/configurations.spec.ts index 74193c95a49..c3b67c1ca46 100644 --- a/packages/middleware-retry/src/configurations.spec.ts +++ b/packages/middleware-retry/src/configurations.spec.ts @@ -1,5 +1,6 @@ import { normalizeProvider } from "@smithy/util-middleware"; import { AdaptiveRetryStrategy, DEFAULT_MAX_ATTEMPTS, StandardRetryStrategy } from "@smithy/util-retry"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { CONFIG_MAX_ATTEMPTS, @@ -8,20 +9,20 @@ import { resolveRetryConfig, } from "./configurations"; -jest.mock("@smithy/util-middleware"); -jest.mock("@smithy/util-retry"); +vi.mock("@smithy/util-middleware"); +vi.mock("@smithy/util-retry"); describe(resolveRetryConfig.name, () => { - const retryMode = jest.fn() as any; + const retryMode = vi.fn() as any; beforeEach(() => { - (normalizeProvider as jest.Mock).mockImplementation((input) => + vi.mocked(normalizeProvider).mockImplementation((input) => typeof input === "function" ? input : () => Promise.resolve(input) ); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("maxAttempts", () => { @@ -39,7 +40,7 @@ describe(resolveRetryConfig.name, () => { describe("retryStrategy", () => { it("passes retryStrategy if present", () => { const mockRetryStrategy = { - retry: jest.fn(), + retry: vi.fn(), }; const { retryStrategy } = resolveRetryConfig({ retryMode, @@ -57,9 +58,9 @@ describe(resolveRetryConfig.name, () => { it(`when maxAttempts=${maxAttempts}`, async () => { const { retryStrategy } = resolveRetryConfig({ maxAttempts, retryMode }); await retryStrategy(); - expect(StandardRetryStrategy as jest.Mock).toHaveBeenCalledTimes(1); - expect(AdaptiveRetryStrategy as jest.Mock).not.toHaveBeenCalled(); - const output = await (StandardRetryStrategy as jest.Mock).mock.calls[0][0](); + expect(vi.mocked(StandardRetryStrategy)).toHaveBeenCalledTimes(1); + expect(vi.mocked(AdaptiveRetryStrategy)).not.toHaveBeenCalled(); + const output = await vi.mocked(StandardRetryStrategy).mock.calls[0][0](); expect(output).toStrictEqual(maxAttempts); }); } @@ -76,9 +77,9 @@ describe(resolveRetryConfig.name, () => { const { retryStrategy } = resolveRetryConfig({ maxAttempts, retryMode }); await retryStrategy(); expect(retryMode).toHaveBeenCalledTimes(1); - expect(StandardRetryStrategy as jest.Mock).toHaveBeenCalledTimes(1); - expect(AdaptiveRetryStrategy as jest.Mock).not.toHaveBeenCalled(); - const output = await (StandardRetryStrategy as jest.Mock).mock.calls[0][0](); + expect(vi.mocked(StandardRetryStrategy)).toHaveBeenCalledTimes(1); + expect(vi.mocked(AdaptiveRetryStrategy)).not.toHaveBeenCalled(); + const output = await vi.mocked(StandardRetryStrategy).mock.calls[0][0](); expect(output).toStrictEqual(maxAttempts); }); } @@ -94,9 +95,9 @@ describe(resolveRetryConfig.name, () => { it(`when maxAttempts=${maxAttempts}`, async () => { const { retryStrategy } = resolveRetryConfig({ maxAttempts, retryMode }); await retryStrategy(); - expect(StandardRetryStrategy as jest.Mock).not.toHaveBeenCalled(); - expect(AdaptiveRetryStrategy as jest.Mock).toHaveBeenCalledTimes(1); - const output = await (AdaptiveRetryStrategy as jest.Mock).mock.calls[0][0](); + expect(vi.mocked(StandardRetryStrategy)).not.toHaveBeenCalled(); + expect(vi.mocked(AdaptiveRetryStrategy)).toHaveBeenCalledTimes(1); + const output = await vi.mocked(AdaptiveRetryStrategy).mock.calls[0][0](); expect(output).toStrictEqual(maxAttempts); }); } @@ -113,9 +114,9 @@ describe(resolveRetryConfig.name, () => { const { retryStrategy } = resolveRetryConfig({ maxAttempts, retryMode }); await retryStrategy(); expect(retryMode).toHaveBeenCalledTimes(1); - expect(StandardRetryStrategy as jest.Mock).not.toHaveBeenCalled(); - expect(AdaptiveRetryStrategy as jest.Mock).toHaveBeenCalledTimes(1); - const output = await (AdaptiveRetryStrategy as jest.Mock).mock.calls[0][0](); + expect(vi.mocked(StandardRetryStrategy)).not.toHaveBeenCalled(); + expect(vi.mocked(AdaptiveRetryStrategy)).toHaveBeenCalledTimes(1); + const output = await vi.mocked(AdaptiveRetryStrategy).mock.calls[0][0](); expect(output).toStrictEqual(maxAttempts); }); } diff --git a/packages/middleware-retry/src/defaultRetryQuota.spec.ts b/packages/middleware-retry/src/defaultRetryQuota.spec.ts index 61f77024fe9..40afcdca047 100644 --- a/packages/middleware-retry/src/defaultRetryQuota.spec.ts +++ b/packages/middleware-retry/src/defaultRetryQuota.spec.ts @@ -1,5 +1,6 @@ import { SdkError } from "@smithy/types"; import { INITIAL_RETRY_TOKENS, NO_RETRY_INCREMENT, RETRY_COST, TIMEOUT_RETRY_COST } from "@smithy/util-retry"; +import { describe, expect, test as it } from "vitest"; import { getDefaultRetryQuota } from "./defaultRetryQuota"; diff --git a/packages/middleware-retry/src/delayDecider.spec.ts b/packages/middleware-retry/src/delayDecider.spec.ts index 4318dc138b3..38fb1784f0d 100644 --- a/packages/middleware-retry/src/delayDecider.spec.ts +++ b/packages/middleware-retry/src/delayDecider.spec.ts @@ -1,4 +1,5 @@ import { MAXIMUM_RETRY_DELAY } from "@smithy/util-retry"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { defaultDelayDecider } from "./delayDecider"; @@ -6,7 +7,7 @@ describe("defaultDelayDecider", () => { const mathDotRandom = Math.random; beforeEach(() => { - Math.random = jest.fn().mockReturnValue(1); + Math.random = vi.fn().mockReturnValue(1); }); afterEach(() => { @@ -42,7 +43,7 @@ describe("defaultDelayDecider", () => { const delayBase = 100; const expectedDelay = Math.floor(mockRandomValue * 2 ** attempts * delayBase); it(`(${delayBase}, ${attempts}) with mock Math.random=${mockRandomValue} returns ${expectedDelay}`, () => { - Math.random = jest.fn().mockReturnValue(mockRandomValue); + Math.random = vi.fn().mockReturnValue(mockRandomValue); expect(defaultDelayDecider(delayBase, attempts)).toBe(expectedDelay); }); }); diff --git a/packages/middleware-retry/src/middleware-retry.integ.spec.ts b/packages/middleware-retry/src/middleware-retry.integ.spec.ts index 704b8181056..f2c0d368e61 100644 --- a/packages/middleware-retry/src/middleware-retry.integ.spec.ts +++ b/packages/middleware-retry/src/middleware-retry.integ.spec.ts @@ -1,6 +1,8 @@ -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, expect, test as it } from "vitest"; import { Weather } from "weather"; +import { requireRequestsFrom } from "../../../private/util-test/src/index"; + describe("middleware-retry", () => { describe(Weather.name, () => { it("should set retry headers", async () => { diff --git a/packages/middleware-retry/src/omitRetryHeadersMiddleware.spec.ts b/packages/middleware-retry/src/omitRetryHeadersMiddleware.spec.ts index a6d15b2686b..ba5a83a9957 100644 --- a/packages/middleware-retry/src/omitRetryHeadersMiddleware.spec.ts +++ b/packages/middleware-retry/src/omitRetryHeadersMiddleware.spec.ts @@ -1,6 +1,7 @@ import { HttpRequest } from "@smithy/protocol-http"; import { FinalizeHandlerArguments, MiddlewareStack } from "@smithy/types"; import { INVOCATION_ID_HEADER, REQUEST_HEADER } from "@smithy/util-retry"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { getOmitRetryHeadersPlugin, @@ -10,12 +11,12 @@ import { describe("getOmitRetryHeadersPlugin", () => { const mockClientStack = { - add: jest.fn(), - addRelativeTo: jest.fn(), + add: vi.fn(), + addRelativeTo: vi.fn(), }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it(`adds omitRetryHeadersMiddleware`, () => { @@ -27,11 +28,11 @@ describe("getOmitRetryHeadersPlugin", () => { describe("omitRetryHeadersMiddleware", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("remove retry headers", async () => { - const next = jest.fn(); + const next = vi.fn(); const args = { request: new HttpRequest({ headers: { diff --git a/packages/middleware-retry/src/retryDecider.spec.ts b/packages/middleware-retry/src/retryDecider.spec.ts index c1934f881f6..0120d49149c 100644 --- a/packages/middleware-retry/src/retryDecider.spec.ts +++ b/packages/middleware-retry/src/retryDecider.spec.ts @@ -5,74 +5,75 @@ import { isTransientError, } from "@smithy/service-error-classification"; import { SdkError } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { defaultRetryDecider } from "./retryDecider"; -jest.mock("@smithy/service-error-classification"); +vi.mock("@smithy/service-error-classification"); describe("defaultRetryDecider", () => { const createMockError = () => Object.assign(new Error(), { $metadata: {} }) as SdkError; beforeEach(() => { - (isRetryableByTrait as jest.Mock).mockReturnValue(false); - (isClockSkewError as jest.Mock).mockReturnValue(false); - (isThrottlingError as jest.Mock).mockReturnValue(false); - (isTransientError as jest.Mock).mockReturnValue(false); + vi.mocked(isRetryableByTrait).mockReturnValue(false); + vi.mocked(isClockSkewError).mockReturnValue(false); + vi.mocked(isThrottlingError).mockReturnValue(false); + vi.mocked(isTransientError).mockReturnValue(false); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should return false when the provided error is falsy", () => { expect(defaultRetryDecider(null as any)).toBe(false); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(0); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(0); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(0); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(0); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(0); }); it("should return true for RetryableByTrait error", () => { - (isRetryableByTrait as jest.Mock).mockReturnValueOnce(true); + vi.mocked(isRetryableByTrait).mockReturnValueOnce(true); expect(defaultRetryDecider(createMockError())).toBe(true); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(1); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(0); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(0); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(0); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(0); }); it("should return true for ClockSkewError", () => { - (isClockSkewError as jest.Mock).mockReturnValueOnce(true); + vi.mocked(isClockSkewError).mockReturnValueOnce(true); expect(defaultRetryDecider(createMockError())).toBe(true); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(1); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(0); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(0); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(0); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(0); }); it("should return true for ThrottlingError", () => { - (isThrottlingError as jest.Mock).mockReturnValueOnce(true); + vi.mocked(isThrottlingError).mockReturnValueOnce(true); expect(defaultRetryDecider(createMockError())).toBe(true); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(1); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(0); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(0); }); it("should return true for TransientError", () => { - (isTransientError as jest.Mock).mockReturnValueOnce(true); + vi.mocked(isTransientError).mockReturnValueOnce(true); expect(defaultRetryDecider(createMockError())).toBe(true); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(1); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(1); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(1); }); it("should return false for other errors", () => { expect(defaultRetryDecider(createMockError())).toBe(false); - expect(isRetryableByTrait as jest.Mock).toHaveBeenCalledTimes(1); - expect(isClockSkewError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isThrottlingError as jest.Mock).toHaveBeenCalledTimes(1); - expect(isTransientError as jest.Mock).toHaveBeenCalledTimes(1); + expect(vi.mocked(isRetryableByTrait)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isClockSkewError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isThrottlingError)).toHaveBeenCalledTimes(1); + expect(vi.mocked(isTransientError)).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/middleware-retry/src/retryMiddleware.spec.ts b/packages/middleware-retry/src/retryMiddleware.spec.ts index a76a618dd2a..f13081505a2 100644 --- a/packages/middleware-retry/src/retryMiddleware.spec.ts +++ b/packages/middleware-retry/src/retryMiddleware.spec.ts @@ -3,36 +3,37 @@ import { isServerError, isThrottlingError, isTransientError } from "@smithy/serv import { FinalizeHandlerArguments, HandlerExecutionContext, MiddlewareStack } from "@smithy/types"; import { INVOCATION_ID_HEADER, REQUEST_HEADER } from "@smithy/util-retry"; import { v4 } from "uuid"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getRetryPlugin, retryMiddleware, retryMiddlewareOptions } from "./retryMiddleware"; -jest.mock("@smithy/service-error-classification"); -jest.mock("@smithy/protocol-http"); -jest.mock("uuid"); +vi.mock("@smithy/service-error-classification"); +vi.mock("@smithy/protocol-http"); +vi.mock("uuid"); describe(getRetryPlugin.name, () => { const mockClientStack = { - add: jest.fn(), + add: vi.fn(), }; const mockRetryStrategy = { mode: "mock", - retry: jest.fn(), + retry: vi.fn(), }; beforeEach(() => { - (isThrottlingError as jest.Mock).mockReturnValue(false); - (isTransientError as jest.Mock).mockReturnValue(false); - (isServerError as jest.Mock).mockReturnValue(false); - (HttpRequest as unknown as jest.Mock).mockReturnValue({ - isInstance: jest.fn().mockReturnValue(false), + vi.mocked(isThrottlingError).mockReturnValue(false); + vi.mocked(isTransientError).mockReturnValue(false); + vi.mocked(isServerError).mockReturnValue(false); + (HttpRequest as unknown as any).mockReturnValue({ + isInstance: vi.fn().mockReturnValue(false), }); - (HttpResponse as unknown as jest.Mock).mockReturnValue({ - isInstance: jest.fn().mockReturnValue(false), + (HttpResponse as unknown as any).mockReturnValue({ + isInstance: vi.fn().mockReturnValue(false), }); - (v4 as jest.Mock).mockReturnValue("42"); + vi.mocked(v4).mockReturnValue("42"); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("adds retryMiddleware", () => { @@ -40,7 +41,7 @@ describe(getRetryPlugin.name, () => { it(`when maxAttempts=${maxAttempts}`, () => { getRetryPlugin({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue(mockRetryStrategy), + retryStrategy: vi.fn().mockResolvedValue(mockRetryStrategy), }).applyToStack(mockClientStack as unknown as MiddlewareStack); expect(mockClientStack.add).toHaveBeenCalledTimes(1); expect(mockClientStack.add.mock.calls[0][1]).toEqual(retryMiddlewareOptions); @@ -52,16 +53,16 @@ describe(getRetryPlugin.name, () => { describe(retryMiddleware.name, () => { const maxAttempts = 2; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("RetryStrategy", () => { const mockRetryStrategy = { mode: "mock", - retry: jest.fn(), + retry: vi.fn(), }; it("calls retryStrategy.retry with next and args", async () => { - const next = jest.fn(); + const next = vi.fn(); const args = { request: { headers: {} }, }; @@ -69,7 +70,7 @@ describe(retryMiddleware.name, () => { await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -95,9 +96,9 @@ describe(retryMiddleware.name, () => { }; const mockRetryStrategy = { mode: "mock", - acquireInitialRetryToken: jest.fn().mockResolvedValue(mockRetryToken), - refreshRetryTokenForRetry: jest.fn().mockResolvedValue(mockRetryToken), - recordSuccess: jest.fn(), + acquireInitialRetryToken: vi.fn().mockResolvedValue(mockRetryToken), + refreshRetryTokenForRetry: vi.fn().mockResolvedValue(mockRetryToken), + recordSuccess: vi.fn(), }; const mockResponse = "mockResponse"; const mockSuccess = { @@ -117,10 +118,10 @@ describe(retryMiddleware.name, () => { }; it("calls acquireInitialRetryToken and records success when next succeeds", async () => { - const next = jest.fn().mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockResolvedValueOnce(mockSuccess); const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -135,22 +136,22 @@ describe(retryMiddleware.name, () => { describe("throws when token cannot be refreshed", () => { it("throw last request error", async () => { const requestError = new Error("mockRequestError"); - (isThrottlingError as jest.Mock).mockReturnValue(true); - const next = jest.fn().mockRejectedValue(requestError); + vi.mocked(isThrottlingError).mockReturnValue(true); + const next = vi.fn().mockRejectedValue(requestError); const errorInfo = { error: requestError, errorType: "THROTTLING", }; const mockRetryStrategy = { mode: "mock", - acquireInitialRetryToken: jest.fn().mockResolvedValue(mockRetryToken), - refreshRetryTokenForRetry: jest.fn().mockRejectedValue(new Error("Cannot refresh token")), - recordSuccess: jest.fn(), + acquireInitialRetryToken: vi.fn().mockResolvedValue(mockRetryToken), + refreshRetryTokenForRetry: vi.fn().mockRejectedValue(new Error("Cannot refresh token")), + recordSuccess: vi.fn(), }; try { await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -170,15 +171,15 @@ describe(retryMiddleware.name, () => { describe("calls acquireInitialRetryToken and refreshes retry token", () => { const mockError = new Error("mockError"); it("sets throttling error type", async () => { - (isThrottlingError as jest.Mock).mockReturnValue(true); - const next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); + vi.mocked(isThrottlingError).mockReturnValue(true); + const next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); const errorInfo = { error: mockError, errorType: "THROTTLING", }; const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -191,16 +192,16 @@ describe(retryMiddleware.name, () => { expect(output.$metadata.totalRetryDelay).toBeDefined(); }); it("sets transient error type", async () => { - (isTransientError as jest.Mock).mockReturnValue(true); - (isThrottlingError as jest.Mock).mockReturnValue(false); - const next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); + vi.mocked(isTransientError).mockReturnValue(true); + vi.mocked(isThrottlingError).mockReturnValue(false); + const next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); const errorInfo = { error: mockError, errorType: "TRANSIENT", }; const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -213,17 +214,17 @@ describe(retryMiddleware.name, () => { expect(output.$metadata.totalRetryDelay).toBeDefined(); }); it("sets server error type", async () => { - (isServerError as jest.Mock).mockReturnValue(true); - (isTransientError as jest.Mock).mockReturnValue(false); - (isThrottlingError as jest.Mock).mockReturnValue(false); - const next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); + vi.mocked(isServerError).mockReturnValue(true); + vi.mocked(isTransientError).mockReturnValue(false); + vi.mocked(isThrottlingError).mockReturnValue(false); + const next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); const errorInfo = { error: mockError, errorType: "SERVER_ERROR", }; const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -236,17 +237,17 @@ describe(retryMiddleware.name, () => { expect(output.$metadata.totalRetryDelay).toBeDefined(); }); it("sets client error type", async () => { - (isServerError as jest.Mock).mockReturnValue(false); - (isTransientError as jest.Mock).mockReturnValue(false); - (isThrottlingError as jest.Mock).mockReturnValue(false); - const next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); + vi.mocked(isServerError).mockReturnValue(false); + vi.mocked(isTransientError).mockReturnValue(false); + vi.mocked(isThrottlingError).mockReturnValue(false); + const next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); const errorInfo = { error: mockError, errorType: "CLIENT_ERROR", }; const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -262,20 +263,20 @@ describe(retryMiddleware.name, () => { describe("when retry-after is not set", () => { it("should not set retryAfter in errorInfo", async () => { const { isInstance } = HttpResponse; - (isInstance as unknown as jest.Mock).mockReturnValue(true); + (isInstance as unknown as any).mockReturnValue(true); Object.defineProperty(mockError, "$response", { value: { headers: { ["other-header"]: "foo" }, }, }); - const next = jest.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockRejectedValueOnce(mockError).mockResolvedValueOnce(mockSuccess); const errorInfo = { error: mockError, errorType: "CLIENT_ERROR", }; const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -293,7 +294,7 @@ describe(retryMiddleware.name, () => { const now = Date.now(); const retryAfterDate = new Date(now + 3000); const { isInstance } = HttpResponse; - (isInstance as unknown as jest.Mock).mockReturnValue(true); + (isInstance as unknown as any).mockReturnValue(true); const errorInfo = { error: mockError, errorType: "CLIENT_ERROR", @@ -301,10 +302,10 @@ describe(retryMiddleware.name, () => { }; it("parses retry-after from date string", async () => { const error = getErrorWithValues(retryAfterDate.toISOString()); - const next = jest.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -318,10 +319,10 @@ describe(retryMiddleware.name, () => { }); it("parses retry-after from seconds", async () => { const error = getErrorWithValues(retryAfterDate.getTime() / 1000); - const next = jest.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -335,10 +336,10 @@ describe(retryMiddleware.name, () => { }); it("parses retry-after from Retry-After header name", async () => { const error = getErrorWithValues(retryAfterDate.toISOString(), "Retry-After"); - const next = jest.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); const { output } = await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -350,17 +351,17 @@ describe(retryMiddleware.name, () => { expect(output.$metadata.attempts).toBe(2); expect(output.$metadata.totalRetryDelay).toBeDefined(); }); - (isInstance as unknown as jest.Mock).mockReturnValue(false); + (isInstance as unknown as any).mockReturnValue(false); }); }); describe("retry headers", () => { describe("not added if HttpRequest.isInstance returns false", () => { it(`retry informational header: ${INVOCATION_ID_HEADER}`, async () => { - const next = jest.fn().mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockResolvedValueOnce(mockSuccess); await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -370,10 +371,10 @@ describe(retryMiddleware.name, () => { }); }); it(`header for each attempt as ${REQUEST_HEADER}`, async () => { - const next = jest.fn().mockResolvedValueOnce(mockSuccess); + const next = vi.fn().mockResolvedValueOnce(mockSuccess); await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -387,12 +388,12 @@ describe(retryMiddleware.name, () => { const retryAfterDate = new Date(Date.now() + 3000); const error = getErrorWithValues(retryAfterDate.toISOString()); const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); - (isThrottlingError as jest.Mock).mockReturnValue(true); - const next = jest.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); + (isInstance as unknown as any).mockReturnValue(true); + vi.mocked(isThrottlingError).mockReturnValue(true); + const next = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context @@ -405,12 +406,12 @@ describe(retryMiddleware.name, () => { const retryAfterDate = new Date(Date.now() + 3000); const error = getErrorWithValues(retryAfterDate.toISOString()); const { isInstance } = HttpRequest; - (isInstance as unknown as jest.Mock).mockReturnValue(true); - (isThrottlingError as jest.Mock).mockReturnValue(true); - const next = jest.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); + (isInstance as unknown as any).mockReturnValue(true); + vi.mocked(isThrottlingError).mockReturnValue(true); + const next = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(mockSuccess); await retryMiddleware({ maxAttempts: () => Promise.resolve(maxAttempts), - retryStrategy: jest.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), + retryStrategy: vi.fn().mockResolvedValue({ ...mockRetryStrategy, maxAttempts }), })( next, context diff --git a/packages/middleware-retry/vitest.config.integ.ts b/packages/middleware-retry/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/middleware-retry/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-retry/vitest.config.ts b/packages/middleware-retry/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/middleware-retry/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-serde/jest.config.integ.js b/packages/middleware-serde/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/middleware-serde/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/middleware-serde/jest.config.js b/packages/middleware-serde/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-serde/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-serde/package.json b/packages/middleware-serde/package.json index 11e45f28633..9faa88f158a 100644 --- a/packages/middleware-serde/package.json +++ b/packages/middleware-serde/package.json @@ -11,8 +11,10 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test": "yarn g:vitest run", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/middleware-serde/src/deserializerMiddleware.spec.ts b/packages/middleware-serde/src/deserializerMiddleware.spec.ts index 2e870e02e69..de19644bfa3 100644 --- a/packages/middleware-serde/src/deserializerMiddleware.spec.ts +++ b/packages/middleware-serde/src/deserializerMiddleware.spec.ts @@ -1,10 +1,11 @@ import { EndpointBearer, SerdeFunctions } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { deserializerMiddleware } from "./deserializerMiddleware"; describe("deserializerMiddleware", () => { - const mockNext = jest.fn(); - const mockDeserializer = jest.fn(); + const mockNext = vi.fn(); + const mockDeserializer = vi.fn(); const mockOptions = { endpoint: () => @@ -51,7 +52,7 @@ describe("deserializerMiddleware", () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("calls deserializer and populates response object", async () => { diff --git a/packages/middleware-serde/src/middleware-serde.integ.spec.ts b/packages/middleware-serde/src/middleware-serde.integ.spec.ts index c9bca189313..5e60de61afb 100644 --- a/packages/middleware-serde/src/middleware-serde.integ.spec.ts +++ b/packages/middleware-serde/src/middleware-serde.integ.spec.ts @@ -1,6 +1,8 @@ -import { requireRequestsFrom } from "@smithy/util-test"; +import { describe, test as it } from "vitest"; import { Weather } from "weather"; +import { requireRequestsFrom } from "../../../private/util-test/src/index"; + describe("middleware-serde", () => { describe(Weather.name, () => { it("should serialize TestProtocol", async () => { diff --git a/packages/middleware-serde/src/serializerMiddleware.spec.ts b/packages/middleware-serde/src/serializerMiddleware.spec.ts index 3b5c0ec3f52..3e2977f89f7 100644 --- a/packages/middleware-serde/src/serializerMiddleware.spec.ts +++ b/packages/middleware-serde/src/serializerMiddleware.spec.ts @@ -1,10 +1,11 @@ import { EndpointBearer, SerdeFunctions } from "@smithy/types"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { serializerMiddleware } from "./serializerMiddleware"; describe("serializerMiddleware", () => { - const mockNext = jest.fn(); - const mockSerializer = jest.fn(); + const mockNext = vi.fn(); + const mockSerializer = vi.fn(); const mockOptions = { endpoint: () => diff --git a/packages/middleware-serde/vitest.config.integ.ts b/packages/middleware-serde/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/middleware-serde/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-serde/vitest.config.ts b/packages/middleware-serde/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/middleware-serde/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/middleware-stack/jest.config.js b/packages/middleware-stack/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/middleware-stack/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-stack/package.json b/packages/middleware-stack/package.json index 3bfbcecd9df..432c15e5be1 100644 --- a/packages/middleware-stack/package.json +++ b/packages/middleware-stack/package.json @@ -13,7 +13,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/middleware-stack/src/MiddlewareStack.spec.ts b/packages/middleware-stack/src/MiddlewareStack.spec.ts index da9c3cc6b8b..d3c8ce7a3c8 100644 --- a/packages/middleware-stack/src/MiddlewareStack.spec.ts +++ b/packages/middleware-stack/src/MiddlewareStack.spec.ts @@ -6,6 +6,7 @@ import { InitializeHandler, Pluggable, } from "@smithy/types"; +import { describe, expect, test as it, vi } from "vitest"; import { constructStack } from "./MiddlewareStack"; @@ -53,7 +54,7 @@ describe("MiddlewareStack", () => { priority: "low", step: "deserialize", }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); @@ -92,7 +93,7 @@ describe("MiddlewareStack", () => { const stack = constructStack(); stack.add(getConcatMiddleware("A"), { name: "A" }); stack.add(getConcatMiddleware("override"), { name: "A", override: true }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -105,7 +106,7 @@ describe("MiddlewareStack", () => { const stack = constructStack(); stack.add(getConcatMiddleware("A"), { aliases: ["ALIAS"] }); stack.add(getConcatMiddleware("override"), { name: "ALIAS", override: true }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -118,7 +119,7 @@ describe("MiddlewareStack", () => { const stack = constructStack(); stack.add(getConcatMiddleware("A"), { name: "ALIAS" }); stack.add(getConcatMiddleware("override"), { aliases: ["ALIAS"], override: true }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -209,7 +210,7 @@ describe("MiddlewareStack", () => { relation: "after", toMiddleware: "AliasI", }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -240,7 +241,7 @@ describe("MiddlewareStack", () => { toMiddleware: "AliasF", }); stack.add(getConcatMiddleware("G"), { name: "G" }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -269,7 +270,7 @@ describe("MiddlewareStack", () => { relation: "after", toMiddleware: "A", }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -284,7 +285,7 @@ describe("MiddlewareStack", () => { relation: "before", toMiddleware: "non_exist", }); - const inner = jest.fn(); + const inner = vi.fn(); try { stack.resolve(inner, {} as any); } catch (e) { @@ -303,7 +304,7 @@ describe("MiddlewareStack", () => { toMiddleware: "A", override: true, }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -326,7 +327,7 @@ describe("MiddlewareStack", () => { toMiddleware: "A", override: true, }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -349,7 +350,7 @@ describe("MiddlewareStack", () => { toMiddleware: "A", override: true, }); - const inner = jest.fn(); + const inner = vi.fn(); const composed = stack.resolve(inner, {} as any); await composed({ input: [] }); expect(inner.mock.calls.length).toBe(1); @@ -427,7 +428,7 @@ describe("MiddlewareStack", () => { aliases: ["AliasC"], }); const secondStack = stack.clone(); - const inner = jest.fn(); + const inner = vi.fn(); await secondStack.resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["A", "B", "C"] }); @@ -464,7 +465,7 @@ describe("MiddlewareStack", () => { toMiddleware: "AliasB", }); - const inner = jest.fn(); + const inner = vi.fn(); await stack.concat(secondStack).resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["A", "B", "C", "D"] }); @@ -475,7 +476,7 @@ describe("MiddlewareStack", () => { stack.add(getConcatMiddleware("A")); const secondStack = constructStack(); secondStack.add(getConcatMiddleware("B")); - const inner = jest.fn(); + const inner = vi.fn(); await stack.concat(secondStack).resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["A", "B"] }); @@ -505,7 +506,7 @@ describe("MiddlewareStack", () => { stack.remove("toRemove"); - const inner = jest.fn(); + const inner = vi.fn(); await stack.resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["don't remove me"] }); @@ -527,7 +528,7 @@ describe("MiddlewareStack", () => { stack.remove("toRemove"); - const inner = jest.fn(); + const inner = vi.fn(); await stack.resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["don't remove me"] }); @@ -541,7 +542,7 @@ describe("MiddlewareStack", () => { stack.add(mw, { aliases: ["toRemove2"] }); stack.remove(mw); - const inner = jest.fn(); + const inner = vi.fn(); await stack.resolve(inner, {} as any)({ input: [] }); expect(inner.mock.calls.length).toBe(1); expect(inner).toBeCalledWith({ input: ["don't remove me!"] }); @@ -605,7 +606,7 @@ describe("MiddlewareStack", () => { }, }; stack.use(plugin); - const inner = jest.fn(({ input }: DeserializeHandlerArguments) => { + const inner = vi.fn(({ input }: DeserializeHandlerArguments) => { expect(input).toEqual(["first", "second"]); return Promise.resolve({ response: {} }); }); diff --git a/packages/middleware-stack/vitest.config.ts b/packages/middleware-stack/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/middleware-stack/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/node-config-provider/jest.config.js b/packages/node-config-provider/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/node-config-provider/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/node-config-provider/package.json b/packages/node-config-provider/package.json index 21e591dd3fb..fa056a88459 100644 --- a/packages/node-config-provider/package.json +++ b/packages/node-config-provider/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --passWithNoTests" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/node-config-provider/src/configLoader.spec.ts b/packages/node-config-provider/src/configLoader.spec.ts index c027188bad1..995916c4de5 100644 --- a/packages/node-config-provider/src/configLoader.spec.ts +++ b/packages/node-config-provider/src/configLoader.spec.ts @@ -1,13 +1,14 @@ import { chain, fromStatic, memoize } from "@smithy/property-provider"; import { Profile } from "@smithy/types"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { loadConfig } from "./configLoader"; import { fromEnv } from "./fromEnv"; import { fromSharedConfigFiles, SharedConfigInit } from "./fromSharedConfigFiles"; -jest.mock("./fromEnv"); -jest.mock("./fromSharedConfigFiles"); -jest.mock("@smithy/property-provider"); +vi.mock("./fromEnv"); +vi.mock("./fromSharedConfigFiles"); +vi.mock("@smithy/property-provider"); describe("loadConfig", () => { const configuration: SharedConfigInit = { @@ -15,16 +16,16 @@ describe("loadConfig", () => { }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("passes fromEnv(), fromSharedConfigFiles() and fromStatic() to chain", () => { const mockFromEnvReturn = "mockFromEnvReturn"; - (fromEnv as jest.Mock).mockReturnValueOnce(mockFromEnvReturn); + vi.mocked(fromEnv).mockReturnValueOnce(mockFromEnvReturn); const mockFromSharedConfigFilesReturn = "mockFromSharedConfigFilesReturn"; - (fromSharedConfigFiles as jest.Mock).mockReturnValueOnce(mockFromSharedConfigFilesReturn); + vi.mocked(fromSharedConfigFiles).mockReturnValueOnce(mockFromSharedConfigFilesReturn); const mockFromStatic = "mockFromStatic"; - (fromStatic as jest.Mock).mockReturnValueOnce(mockFromStatic); + vi.mocked(fromStatic).mockReturnValueOnce(mockFromStatic); // Using Record instead of NodeJS.ProcessEnv, in order to not get type errors in non node environments const envVarSelector = (env: Record) => env["AWS_CONFIG_FOO"]; const configKey = (profile: Profile) => profile["aws_config_foo"]; @@ -49,7 +50,7 @@ describe("loadConfig", () => { it("passes output of chain to memoize", () => { const mockChainReturn = "mockChainReturn"; - (chain as jest.Mock).mockReturnValueOnce(mockChainReturn); + vi.mocked(chain).mockReturnValueOnce(mockChainReturn); loadConfig({} as any); expect(chain).toHaveBeenCalledTimes(1); expect(memoize).toHaveBeenCalledTimes(1); @@ -58,7 +59,7 @@ describe("loadConfig", () => { it("returns output memoize", () => { const mockMemoizeReturn = "mockMemoizeReturn"; - (memoize as jest.Mock).mockReturnValueOnce(mockMemoizeReturn); + vi.mocked(memoize).mockReturnValueOnce(mockMemoizeReturn); expect(loadConfig({} as any)).toEqual(mockMemoizeReturn); }); }); diff --git a/packages/node-config-provider/src/fromEnv.spec.ts b/packages/node-config-provider/src/fromEnv.spec.ts index 2b1508396a9..084468a0ee1 100644 --- a/packages/node-config-provider/src/fromEnv.spec.ts +++ b/packages/node-config-provider/src/fromEnv.spec.ts @@ -1,4 +1,5 @@ import { CredentialsProviderError } from "@smithy/property-provider"; +import { afterAll, beforeEach, describe, expect, test as it, vi } from "vitest"; import { fromEnv, GetterFromEnv } from "./fromEnv"; @@ -20,7 +21,7 @@ describe("fromEnv", () => { }); describe("CredentialsProviderError", () => { - it("is behaving as expected cross-package in jest", () => { + it("is behaving as expected cross-package in vitest", () => { expect(new CredentialsProviderError("msg", {}).message).toEqual("msg"); expect(new CredentialsProviderError("msg", {}).name).toEqual("CredentialsProviderError"); }); @@ -34,7 +35,7 @@ describe("fromEnv", () => { it("return complex value from the getter", () => { type Value = { Foo: string }; const value: Value = { Foo: "bar" }; - const getter: (env: any) => Value = jest.fn().mockReturnValue(value); + const getter: (env: any) => Value = vi.fn().mockReturnValue(value); // Validate the generic type works return expect(fromEnv(getter)()).resolves.toEqual(value); }); @@ -47,7 +48,7 @@ describe("fromEnv", () => { it("throws when the getter function throws", () => { const exception = new Error("Exception when getting the config"); - const getter: (env: any) => any = jest.fn().mockRejectedValue(exception); + const getter: (env: any) => any = vi.fn().mockRejectedValue(exception); return expect(fromEnv(getter)()).rejects.toEqual(exception); }); }); diff --git a/packages/node-config-provider/src/fromSharedConfigFiles.spec.ts b/packages/node-config-provider/src/fromSharedConfigFiles.spec.ts index 3382dc9d947..fa8dffc36df 100644 --- a/packages/node-config-provider/src/fromSharedConfigFiles.spec.ts +++ b/packages/node-config-provider/src/fromSharedConfigFiles.spec.ts @@ -1,12 +1,13 @@ import { CredentialsProviderError } from "@smithy/property-provider"; import { getProfileName, loadSharedConfigFiles } from "@smithy/shared-ini-file-loader"; import { ParsedIniData, Profile } from "@smithy/types"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { fromSharedConfigFiles, GetterFromConfig, SharedConfigInit } from "./fromSharedConfigFiles"; -jest.mock("@smithy/shared-ini-file-loader", () => ({ - getProfileName: jest.fn(), - loadSharedConfigFiles: jest.fn(), +vi.mock("@smithy/shared-ini-file-loader", () => ({ + getProfileName: vi.fn(), + loadSharedConfigFiles: vi.fn(), })); describe("fromSharedConfigFiles", () => { @@ -108,11 +109,11 @@ describe("fromSharedConfigFiles", () => { loadedConfigResolves.forEach( ({ message, iniDataInConfig, iniDataInCredentials, configValueToVerify, profile, preferredFile }) => { it(message, () => { - (loadSharedConfigFiles as jest.Mock).mockResolvedValueOnce({ + vi.mocked(loadSharedConfigFiles).mockResolvedValueOnce({ configFile: iniDataInConfig, credentialsFile: iniDataInCredentials, }); - (getProfileName as jest.Mock).mockReturnValueOnce(profile ?? "default"); + vi.mocked(getProfileName).mockReturnValueOnce(profile ?? "default"); return expect(fromSharedConfigFiles(configGetter, { profile, preferredFile })()).resolves.toBe( configValueToVerify ); @@ -122,11 +123,11 @@ describe("fromSharedConfigFiles", () => { loadedConfigRejects.forEach(({ message, iniDataInConfig, iniDataInCredentials, profile, preferredFile }) => { it(message, () => { - (loadSharedConfigFiles as jest.Mock).mockResolvedValueOnce({ + vi.mocked(loadSharedConfigFiles).mockResolvedValueOnce({ configFile: iniDataInConfig, credentialsFile: iniDataInCredentials, }); - (getProfileName as jest.Mock).mockReturnValueOnce(profile ?? "default"); + vi.mocked(getProfileName).mockReturnValueOnce(profile ?? "default"); return expect(fromSharedConfigFiles(configGetter, { profile, preferredFile })()).rejects.toEqual( getCredentialsProviderError(profile ?? "default") ); @@ -138,7 +139,7 @@ describe("fromSharedConfigFiles", () => { const failGetter = () => { throw new Error(message); }; - (loadSharedConfigFiles as jest.Mock).mockResolvedValueOnce({ + vi.mocked(loadSharedConfigFiles).mockResolvedValueOnce({ configFile: {}, credentialsFile: {}, }); @@ -158,11 +159,11 @@ describe("fromSharedConfigFiles", () => { }; beforeEach(() => { - (loadSharedConfigFiles as jest.Mock).mockResolvedValueOnce(loadedConfigData); + vi.mocked(loadSharedConfigFiles).mockResolvedValueOnce(loadedConfigData); }); it.each(["foo", "default"])("returns config value from %s profile", (profile) => { - (getProfileName as jest.Mock).mockReturnValueOnce(profile); + vi.mocked(getProfileName).mockReturnValueOnce(profile); return expect(fromSharedConfigFiles(configGetter)()).resolves.toBe( loadedConfigData.configFile[profile][CONFIG_KEY] ); diff --git a/packages/node-config-provider/src/fromStatic.spec.ts b/packages/node-config-provider/src/fromStatic.spec.ts index 235d29510f0..edf840501ae 100644 --- a/packages/node-config-provider/src/fromStatic.spec.ts +++ b/packages/node-config-provider/src/fromStatic.spec.ts @@ -1,28 +1,29 @@ import { fromStatic as convertToProvider } from "@smithy/property-provider"; +import { describe, expect, test as it, vi } from "vitest"; import { fromStatic } from "./fromStatic"; -jest.mock("@smithy/property-provider", () => ({ - fromStatic: jest.fn(), +vi.mock("@smithy/property-provider", () => ({ + fromStatic: vi.fn(), })); describe("fromStatic", () => { const value = "default"; it("should convert static values to provider", async () => { - (convertToProvider as jest.Mock).mockReturnValue(value); + vi.mocked(convertToProvider).mockReturnValue(value); fromStatic(value); - expect(convertToProvider as jest.Mock).toHaveBeenCalledWith(value); + expect(vi.mocked(convertToProvider)).toHaveBeenCalledWith(value); }); it("should call the getter function", async () => { - const getter = jest.fn().mockReturnValue(value); + const getter = vi.fn().mockReturnValue(value); const config = fromStatic(getter); expect(await config()).toBe(value); expect(getter).toHaveBeenCalled(); }); it("should call the async provider function", async () => { - const getter = jest.fn().mockResolvedValue(value); + const getter = vi.fn().mockResolvedValue(value); const config = fromStatic(getter); expect(await config()).toBe(value); expect(getter).toHaveBeenCalled(); diff --git a/packages/node-config-provider/vitest.config.ts b/packages/node-config-provider/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/node-config-provider/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/node-http-handler/jest.config.js b/packages/node-http-handler/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/node-http-handler/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/node-http-handler/package.json b/packages/node-http-handler/package.json index 7be742f0c8b..46da5c0ae85 100644 --- a/packages/node-http-handler/package.json +++ b/packages/node-http-handler/package.json @@ -13,7 +13,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest --coverage --forceExit" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/node-http-handler/src/index.spec.ts b/packages/node-http-handler/src/index.spec.ts index 73ec362f4ad..c71f85697f0 100644 --- a/packages/node-http-handler/src/index.spec.ts +++ b/packages/node-http-handler/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { NodeHttpHandler } from "./index"; describe("index", () => { diff --git a/packages/node-http-handler/src/node-http-handler.mock-server.spec.ts b/packages/node-http-handler/src/node-http-handler.mock-server.spec.ts new file mode 100644 index 00000000000..1280c5eba99 --- /dev/null +++ b/packages/node-http-handler/src/node-http-handler.mock-server.spec.ts @@ -0,0 +1,442 @@ +import { AbortController } from "@smithy/abort-controller"; +import { HttpRequest } from "@smithy/protocol-http"; +import http, { Server as HttpServer } from "http"; +import https, { Server as HttpsServer } from "https"; +import { AddressInfo } from "net"; +import { afterAll, afterEach, beforeAll, describe, expect, test as it, vi } from "vitest"; + +import { NodeHttpHandler } from "./node-http-handler"; +import { ReadFromBuffers } from "./readable.mock"; +import { + createContinueResponseFunction, + createMirrorResponseFunction, + createMockHttpServer, + createMockHttpsServer, + createResponseFunction, + getResponseBody, +} from "./server.mock"; + +vi.mock("http", async () => { + const actual = (await vi.importActual("http")) as any; + const pkg = { + ...actual, + request: vi.fn().mockImplementation(actual.request), + }; + return { + ...pkg, + default: pkg, + }; +}); + +vi.mock("https", async () => { + const actual = (await vi.importActual("https")) as any; + const pkg = { + ...actual, + request: vi.fn().mockImplementation(actual.request), + }; + return { + ...pkg, + default: pkg, + }; +}); + +import { request as hRequest } from "http"; +import { request as hsRequest } from "https"; + +describe("http", () => { + let mockHttpServer: HttpServer; + beforeAll(() => { + mockHttpServer = createMockHttpServer().listen(54321); + }); + + afterEach(() => { + mockHttpServer.removeAllListeners("request"); + mockHttpServer.removeAllListeners("checkContinue"); + }); + + afterAll(() => { + mockHttpServer.close(); + }); + + it("has metadata", () => { + const nodeHttpHandler = new NodeHttpHandler(); + expect(nodeHttpHandler.metadata.handlerProtocol).toContain("http/1.1"); + }); + + it("can send http requests", async () => { + const mockResponse = { + statusCode: 200, + reason: "OK", + headers: {}, + body: "test", + }; + mockHttpServer.addListener("request", createResponseFunction(mockResponse)); + const nodeHttpHandler = new NodeHttpHandler(); + + const { response } = await nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: {}, + }), + {} + ); + + expect(response.statusCode).toEqual(mockResponse.statusCode); + expect(response.reason).toEqual(mockResponse.reason); + expect(response.headers).toBeDefined(); + expect(response.headers).toMatchObject(mockResponse.headers); + expect(response.body).toBeDefined(); + }); + + [ + { name: "buffer", body: Buffer.from("Buffering🚀") }, + { name: "uint8Array", body: Uint8Array.from(Buffer.from("uint8Array 🚀")) }, + { name: "string", body: Buffer.from("string-test 🚀") }, + { name: "uint8Array subarray", body: Uint8Array.from(Buffer.from("test")).subarray(1, 3) }, + { name: "buffer subarray", body: Buffer.from("test").subarray(1, 3) }, + ].forEach(({ body, name }) => { + it(`can send requests with bodies ${name}`, async () => { + const mockResponse = { + statusCode: 200, + headers: {}, + }; + mockHttpServer.addListener("request", createMirrorResponseFunction(mockResponse)); + const nodeHttpHandler = new NodeHttpHandler(); + const { response } = await nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "PUT", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: {}, + body, + }), + {} + ); + + expect(response.statusCode).toEqual(mockResponse.statusCode); + expect(response.headers).toBeDefined(); + expect(response.headers).toMatchObject(mockResponse.headers); + const responseBody = await getResponseBody(response); + expect(responseBody).toEqual(Buffer.from(body).toString()); + }); + }); + + it("can handle expect 100-continue", async () => { + const body = Buffer.from("test"); + const mockResponse = { + statusCode: 200, + headers: {}, + }; + + mockHttpServer.addListener("checkContinue", createContinueResponseFunction(mockResponse)); + let endSpy: any; + let continueWasTriggered = false; + const spy = vi.mocked(hRequest).mockImplementationOnce(() => { + const calls = spy.mock.calls; + const currentIndex = calls.length - 1; + const request = http.request(calls[currentIndex][0], calls[currentIndex][1]); + request.on("continue", () => { + continueWasTriggered = true; + }); + endSpy = vi.spyOn(request, "end"); + + return request; + }); + + const nodeHttpHandler = new NodeHttpHandler(); + const { response } = await nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "PUT", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: { + Expect: "100-continue", + }, + body, + }), + {} + ); + + expect(response.statusCode).toEqual(mockResponse.statusCode); + expect(response.headers).toBeDefined(); + expect(response.headers).toMatchObject(mockResponse.headers); + expect(endSpy!.mock.calls.length).toBe(1); + expect(endSpy!.mock.calls[0][0]).toStrictEqual(body); + expect(continueWasTriggered).toBe(true); + }); + + it("can send requests with streaming bodies", async () => { + const body = new ReadFromBuffers({ + buffers: [Buffer.from("t"), Buffer.from("e"), Buffer.from("s"), Buffer.from("t")], + }); + const inputBodySpy = vi.spyOn(body, "pipe"); + const mockResponse = { + statusCode: 200, + headers: {}, + }; + mockHttpServer.addListener("request", createResponseFunction(mockResponse)); + const nodeHttpHandler = new NodeHttpHandler(); + + const { response } = await nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "PUT", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: {}, + body, + }), + {} + ); + + expect(response.statusCode).toEqual(mockResponse.statusCode); + expect(response.headers).toBeDefined(); + expect(response.headers).toMatchObject(mockResponse.headers); + expect(inputBodySpy.mock.calls.length).toBeTruthy(); + }); + + it("can send requests with Uint8Array bodies", async () => { + const body = Buffer.from([0, 1, 2, 3]); + const mockResponse = { + statusCode: 200, + headers: {}, + }; + mockHttpServer.addListener("request", createResponseFunction(mockResponse)); + let endSpy: any; + const spy = vi.mocked(hRequest).mockImplementationOnce(() => { + const calls = spy.mock.calls; + const currentIndex = calls.length - 1; + const request = http.request(calls[currentIndex][0], calls[currentIndex][1]); + endSpy = vi.spyOn(request, "end"); + return request; + }); + + const nodeHttpHandler = new NodeHttpHandler(); + const { response } = await nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "PUT", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: {}, + body, + }), + {} + ); + + expect(response.statusCode).toEqual(mockResponse.statusCode); + expect(response.headers).toBeDefined(); + expect(response.headers).toMatchObject(mockResponse.headers); + expect(endSpy!.mock.calls.length).toBe(1); + expect(endSpy!.mock.calls[0][0]).toStrictEqual(body); + }); +}); + +describe("https", () => { + const mockHttpsServer: HttpsServer = createMockHttpsServer().listen(54322); + + afterEach(() => { + mockHttpsServer.removeAllListeners("request"); + mockHttpsServer.removeAllListeners("checkContinue"); + }); + + afterAll(() => { + mockHttpsServer.close(); + }); + + it("rejects if the request encounters an error", async () => { + const mockResponse = { + statusCode: 200, + headers: {}, + body: "test", + }; + mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); + const nodeHttpHandler = new NodeHttpHandler(); + + await expect( + nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpsServer.address() as AddressInfo).port, + protocol: "fake:", // trigger a request error + path: "/", + headers: {}, + }), + {} + ) + ).rejects.toHaveProperty("message"); + }); + + it("will not make request if already aborted", async () => { + const mockResponse = { + statusCode: 200, + headers: {}, + body: "test", + }; + mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); + const spy = vi.mocked(hsRequest).mockImplementationOnce(() => { + const calls = spy.mock.calls; + const currentIndex = calls.length - 1; + return https.request(calls[currentIndex][0], calls[currentIndex][1]); + }); + // clear data held from previous tests + spy.mockClear(); + const nodeHttpHandler = new NodeHttpHandler(); + + await expect( + nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpsServer.address() as AddressInfo).port, + protocol: "https:", + path: "/", + headers: {}, + }), + { + abortSignal: { + aborted: true, + onabort: null, + }, + } + ) + ).rejects.toHaveProperty("name", "AbortError"); + + expect(spy.mock.calls.length).toBe(0); + }); + + it(`won't throw uncatchable error in writeRequestBody`, async () => { + const nodeHttpHandler = new NodeHttpHandler(); + + await expect( + nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpsServer.address() as AddressInfo).port, + protocol: "https:", + path: "/", + headers: {}, + body: {}, + }) + ) + ).rejects.toHaveProperty("name", "TypeError"); + }); + + it("will destroy the request when aborted", async () => { + const mockResponse = { + statusCode: 200, + headers: {}, + body: "test", + }; + mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); + let httpRequest: http.ClientRequest; + let reqDestroySpy: any; + const spy = vi.mocked(hsRequest).mockImplementationOnce(() => { + const calls = spy.mock.calls; + const currentIndex = calls.length - 1; + httpRequest = https.request(calls[currentIndex][0], calls[currentIndex][1]); + reqDestroySpy = vi.spyOn(httpRequest, "destroy"); + return httpRequest; + }); + const nodeHttpHandler = new NodeHttpHandler(); + const abortController = new AbortController(); + + setTimeout(() => { + abortController.abort(); + }, 0); + + await expect( + nodeHttpHandler.handle( + new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpsServer.address() as AddressInfo).port, + protocol: "https:", + path: "/", + headers: {}, + }), + { + abortSignal: abortController.signal, + } + ) + ).rejects.toHaveProperty("name", "AbortError"); + + expect(reqDestroySpy.mock.calls.length).toBe(1); + }); +}); + +describe("configs", () => { + const mockResponse = { + statusCode: 200, + statusText: "OK", + headers: {}, + body: "test", + }; + + let mockHttpServer: HttpServer; + let request: HttpRequest; + + beforeAll(() => { + mockHttpServer = createMockHttpServer().listen(54320); + request = new HttpRequest({ + hostname: "localhost", + method: "GET", + port: (mockHttpServer.address() as AddressInfo).port, + protocol: "http:", + path: "/", + headers: {}, + }); + }); + + afterEach(() => { + mockHttpServer.removeAllListeners("request"); + mockHttpServer.removeAllListeners("checkContinue"); + }); + + afterAll(() => { + mockHttpServer.close(); + }); + + it("put HttpClientConfig", async () => { + mockHttpServer.addListener("request", createResponseFunction(mockResponse)); + + const nodeHttpHandler = new NodeHttpHandler(); + const requestTimeout = 200; + + nodeHttpHandler.updateHttpClientConfig("requestTimeout", requestTimeout); + + await nodeHttpHandler.handle(request, {}); + + expect(nodeHttpHandler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); + }); + + it("update existing HttpClientConfig", async () => { + mockHttpServer.addListener("request", createResponseFunction(mockResponse)); + + const nodeHttpHandler = new NodeHttpHandler({ requestTimeout: 200 }); + const requestTimeout = 300; + + nodeHttpHandler.updateHttpClientConfig("requestTimeout", requestTimeout); + + await nodeHttpHandler.handle(request, {}); + + expect(nodeHttpHandler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); + }); + + it("httpHandlerConfigs returns empty object if handle is not called", async () => { + const nodeHttpHandler = new NodeHttpHandler(); + expect(nodeHttpHandler.httpHandlerConfigs()).toEqual({}); + }); +}); diff --git a/packages/node-http-handler/src/node-http-handler.spec.ts b/packages/node-http-handler/src/node-http-handler.spec.ts index c32339cdfc1..58665289e83 100644 --- a/packages/node-http-handler/src/node-http-handler.spec.ts +++ b/packages/node-http-handler/src/node-http-handler.spec.ts @@ -1,43 +1,62 @@ -import { AbortController } from "@smithy/abort-controller"; import { HttpRequest } from "@smithy/protocol-http"; -import http, { Server as HttpServer } from "http"; -import https, { Server as HttpsServer } from "https"; -import { AddressInfo } from "net"; +import http from "http"; +import https from "https"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { NodeHttpHandler } from "./node-http-handler"; -import { ReadFromBuffers } from "./readable.mock"; -import { - createContinueResponseFunction, - createMirrorResponseFunction, - createMockHttpServer, - createMockHttpsServer, - createResponseFunction, - getResponseBody, -} from "./server.mock"; -describe("NodeHttpHandler", () => { - describe("constructor and #handle", () => { - let hRequestSpy: jest.SpyInstance; - let hsRequestSpy: jest.SpyInstance; - const randomMaxSocket = Math.round(Math.random() * 50) + 1; - const mockRequestImpl = (protocol: string) => (_options, cb) => { +vi.mock("http", async () => { + const actual = (await vi.importActual("http")) as any; + const pkg = { + ...actual, + request: vi.fn().mockImplementation((_options, cb) => { cb({ statusCode: 200, body: "body", headers: {}, - protocol, + protocol: "http:", }); - return new http.ClientRequest({ ..._options, protocol }); - }; + return new actual.ClientRequest({ ..._options, protocol: "http:" }); + }), + }; + return { + ...pkg, + default: pkg, + }; +}); - beforeEach(() => { - hRequestSpy = jest.spyOn(http, "request").mockImplementation(mockRequestImpl("http:")); - hsRequestSpy = jest.spyOn(https, "request").mockImplementation(mockRequestImpl("https:")); - }); +vi.mock("https", async () => { + const actual = (await vi.importActual("https")) as any; + const http = (await vi.importActual("http")) as any; + const pkg = { + ...actual, + request: vi.fn().mockImplementation((_options, cb) => { + cb({ + statusCode: 200, + body: "body", + headers: {}, + protocol: "https:", + }); + return new http.ClientRequest({ ..._options, protocol: "https:" }); + }), + }; + return { + ...pkg, + default: pkg, + }; +}); + +import { request as hRequest } from "http"; +import { request as hsRequest } from "https"; + +describe("NodeHttpHandler", () => { + describe("constructor and #handle", () => { + const randomMaxSocket = Math.round(Math.random() * 50) + 1; + + beforeEach(() => {}); afterEach(() => { - hRequestSpy.mockRestore(); - hsRequestSpy.mockRestore(); + vi.clearAllMocks(); }); describe("constructor", () => { @@ -48,8 +67,9 @@ describe("NodeHttpHandler", () => { }); await nodeHttpHandler.handle({} as any); - expect(hRequestSpy.mock.calls[0][0]?.agent.maxSockets).toEqual(37); - expect(hRequestSpy.mock.calls[0][0]?.agent.keepAlive).toEqual(true); + + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.maxSockets).toEqual(37); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.keepAlive).toEqual(true); expect((nodeHttpHandler as any).config.httpsAgent.maxSockets).toEqual(39); expect((nodeHttpHandler as any).config.httpsAgent.keepAlive).toEqual(false); @@ -61,7 +81,7 @@ describe("NodeHttpHandler", () => { ])("sets keepAlive=true by default when input is %s", async (_, option) => { const nodeHttpHandler = new NodeHttpHandler(option); await nodeHttpHandler.handle({} as any); - expect(hRequestSpy.mock.calls[0][0]?.agent.keepAlive).toEqual(true); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.keepAlive).toEqual(true); }); it.each([ @@ -70,7 +90,7 @@ describe("NodeHttpHandler", () => { ])("sets maxSockets=50 by default when input is %s", async (_, option) => { const nodeHttpHandler = new NodeHttpHandler(option); await nodeHttpHandler.handle({} as any); - expect(hRequestSpy.mock.calls[0][0]?.agent.maxSockets).toEqual(50); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.maxSockets).toEqual(50); }); it.each([ @@ -84,8 +104,8 @@ describe("NodeHttpHandler", () => { ])("sets httpAgent when input is %s", async (_, option) => { const nodeHttpHandler = new NodeHttpHandler(option); await nodeHttpHandler.handle({ protocol: "http:", headers: {}, method: "GET", hostname: "localhost" } as any); - expect(hRequestSpy.mock.calls[0][0]?.agent.keepAlive).toEqual(false); - expect(hRequestSpy.mock.calls[0][0]?.agent.maxSockets).toEqual(randomMaxSocket); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.keepAlive).toEqual(false); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.agent.maxSockets).toEqual(randomMaxSocket); }); it.each([ @@ -99,8 +119,8 @@ describe("NodeHttpHandler", () => { ])("sets httpsAgent when input is %s", async (_, option) => { const nodeHttpHandler = new NodeHttpHandler(option); await nodeHttpHandler.handle({ protocol: "https:" } as any); - expect(hsRequestSpy.mock.calls[0][0]?.agent.keepAlive).toEqual(true); - expect(hsRequestSpy.mock.calls[0][0]?.agent.maxSockets).toEqual(randomMaxSocket); + expect(vi.mocked(hsRequest as any).mock.calls[0][0]?.agent.keepAlive).toEqual(true); + expect(vi.mocked(hsRequest as any).mock.calls[0][0]?.agent.maxSockets).toEqual(randomMaxSocket); }); }); @@ -148,10 +168,10 @@ describe("NodeHttpHandler", () => { fragment: "fragment", }; await nodeHttpHandler.handle(httpRequest as any); - expect(hRequestSpy.mock.calls[0][0]?.auth).toEqual("username:password"); - expect(hRequestSpy.mock.calls[0][0]?.host).toEqual("host"); - expect(hRequestSpy.mock.calls[0][0]?.port).toEqual(1234); - expect(hRequestSpy.mock.calls[0][0]?.path).toEqual("/some/path?some=query#fragment"); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.auth).toEqual("username:password"); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.host).toEqual("host"); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.port).toEqual(1234); + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.path).toEqual("/some/path?some=query#fragment"); }); it("removes brackets from hostname", async () => { @@ -169,506 +189,8 @@ describe("NodeHttpHandler", () => { fragment: "fragment", }; await nodeHttpHandler.handle(httpRequest as any); - expect(hRequestSpy.mock.calls[0][0]?.host).toEqual("host"); - }); - }); - }); - - describe("http", () => { - let mockHttpServer: HttpServer; - beforeAll(() => { - mockHttpServer = createMockHttpServer().listen(54321); - }); - - afterEach(() => { - mockHttpServer.removeAllListeners("request"); - mockHttpServer.removeAllListeners("checkContinue"); - }); - - afterAll(() => { - mockHttpServer.close(); - }); - - it("has metadata", () => { - const nodeHttpHandler = new NodeHttpHandler(); - expect(nodeHttpHandler.metadata.handlerProtocol).toContain("http/1.1"); - }); - - it("can send http requests", async () => { - const mockResponse = { - statusCode: 200, - statusText: "OK", - headers: {}, - body: "test", - }; - mockHttpServer.addListener("request", createResponseFunction(mockResponse)); - const nodeHttpHandler = new NodeHttpHandler(); - - const { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: {}, - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.reason).toEqual(mockResponse.statusText); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(response.body).toBeDefined(); - }); - - [ - { name: "buffer", body: Buffer.from("Buffering🚀") }, - { name: "uint8Array", body: Uint8Array.from(Buffer.from("uint8Array 🚀")) }, - { name: "string", body: Buffer.from("string-test 🚀") }, - { name: "uint8Array subarray", body: Uint8Array.from(Buffer.from("test")).subarray(1, 3) }, - { name: "buffer subarray", body: Buffer.from("test").subarray(1, 3) }, - ].forEach(({ body, name }) => { - it(`can send requests with bodies ${name}`, async () => { - const mockResponse = { - statusCode: 200, - headers: {}, - }; - mockHttpServer.addListener("request", createMirrorResponseFunction(mockResponse)); - const nodeHttpHandler = new NodeHttpHandler(); - const { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: {}, - body, - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - const responseBody = await getResponseBody(response); - expect(responseBody).toEqual(Buffer.from(body).toString()); - }); - }); - - it("can handle expect 100-continue", async () => { - const body = Buffer.from("test"); - const mockResponse = { - statusCode: 200, - headers: {}, - }; - - mockHttpServer.addListener("checkContinue", createContinueResponseFunction(mockResponse)); - let endSpy: jest.SpyInstance; - let continueWasTriggered = false; - const spy = jest.spyOn(http, "request").mockImplementationOnce(() => { - const calls = spy.mock.calls; - const currentIndex = calls.length - 1; - const request = http.request(calls[currentIndex][0], calls[currentIndex][1]); - request.on("continue", () => { - continueWasTriggered = true; - }); - endSpy = jest.spyOn(request, "end"); - - return request; - }); - - const nodeHttpHandler = new NodeHttpHandler(); - const { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: { - Expect: "100-continue", - }, - body, - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(endSpy!.mock.calls.length).toBe(1); - expect(endSpy!.mock.calls[0][0]).toStrictEqual(body); - expect(continueWasTriggered).toBe(true); - }); - - it("can send requests with streaming bodies", async () => { - const body = new ReadFromBuffers({ - buffers: [Buffer.from("t"), Buffer.from("e"), Buffer.from("s"), Buffer.from("t")], + expect(vi.mocked(hRequest as any).mock.calls[0][0]?.host).toEqual("host"); }); - const inputBodySpy = jest.spyOn(body, "pipe"); - const mockResponse = { - statusCode: 200, - headers: {}, - }; - mockHttpServer.addListener("request", createResponseFunction(mockResponse)); - const nodeHttpHandler = new NodeHttpHandler(); - - const { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: {}, - body, - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(inputBodySpy.mock.calls.length).toBeTruthy(); - }); - - it("can send requests with Uint8Array bodies", async () => { - const body = Buffer.from([0, 1, 2, 3]); - const mockResponse = { - statusCode: 200, - headers: {}, - }; - mockHttpServer.addListener("request", createResponseFunction(mockResponse)); - let endSpy: jest.SpyInstance; - const spy = jest.spyOn(http, "request").mockImplementationOnce(() => { - const calls = spy.mock.calls; - const currentIndex = calls.length - 1; - const request = http.request(calls[currentIndex][0], calls[currentIndex][1]); - endSpy = jest.spyOn(request, "end"); - return request; - }); - - const nodeHttpHandler = new NodeHttpHandler(); - const { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: {}, - body, - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(endSpy!.mock.calls.length).toBe(1); - expect(endSpy!.mock.calls[0][0]).toStrictEqual(body); - }); - }); - - describe("https", () => { - const mockHttpsServer: HttpsServer = createMockHttpsServer().listen(54322); - - /*beforeEach(() => { - // Setting the NODE_TLS_REJECT_UNAUTHORIZED will allow the unconfigurable - // HTTPS client in getCertificate to skip cert validation, which the - // self-signed cert used for this test's server would fail. The variable - // will be reset to its original value at the end of the test. - process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; - });*/ - - afterEach(() => { - mockHttpsServer.removeAllListeners("request"); - mockHttpsServer.removeAllListeners("checkContinue"); - //process.env.NODE_TLS_REJECT_UNAUTHORIZED = rejectUnauthorizedEnv; - }); - - afterAll(() => { - mockHttpsServer.close(); - }); - /*it("can send https requests", async () => { - const mockResponse = { - statusCode: 200, - headers: {}, - body: "test" - }; - mockHttpsServer.addListener( - "request", - createResponseFunction(mockResponse) - ); - const nodeHttpHandler = new NodeHttpHandler(); - - let { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {} - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(response.body).toBeDefined(); - }); - - it("can send requests with bodies", async () => { - const body = Buffer.from("test"); - const mockResponse = { - statusCode: 200, - headers: {} - }; - mockHttpsServer.addListener( - "request", - createResponseFunction(mockResponse) - ); - const spy = jest.spyOn(https, "request").mockImplementationOnce(() => { - let calls = spy.mock.calls; - let currentIndex = calls.length - 1; - return https.request(calls[currentIndex][0], calls[currentIndex][1]); - }); - - const nodeHttpHandler = new NodeHttpHandler(); - let { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {}, - body - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - }); - - it("can handle expect 100-continue", async () => { - const body = Buffer.from("test"); - const mockResponse = { - statusCode: 200, - headers: {} - }; - - mockHttpsServer.addListener( - "checkContinue", - createContinueResponseFunction(mockResponse) - ); - let endSpy: jest.SpyInstance; - let continueWasTriggered = false; - const spy = jest.spyOn(https, "request").mockImplementationOnce(() => { - let calls = spy.mock.calls; - let currentIndex = calls.length - 1; - const request = https.request( - calls[currentIndex][0], - calls[currentIndex][1] - ); - request.on("continue", () => { - continueWasTriggered = true; - }); - endSpy = jest.spyOn(request, "end"); - - return request; - }); - - const nodeHttpHandler = new NodeHttpHandler(); - let response = await nodeHttpHandler.handle( - { - hostname: "localhost", - method: "PUT", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: { - Expect: "100-continue" - }, - body - }, - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(endSpy!.mock.calls.length).toBe(1); - expect(endSpy!.mock.calls[0][0]).toBe(body); - expect(continueWasTriggered).toBe(true); - }); - - it("can send requests with streaming bodies", async () => { - const body = new ReadFromBuffers({ - buffers: [ - Buffer.from("t"), - Buffer.from("e"), - Buffer.from("s"), - Buffer.from("t") - ] - }); - let inputBodySpy = jest.spyOn(body, "pipe"); - const mockResponse = { - statusCode: 200, - headers: {} - }; - mockHttpsServer.addListener( - "request", - createResponseFunction(mockResponse) - ); - const nodeHttpHandler = new NodeHttpHandler(); - - let { response } = await nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "PUT", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {}, - body - }), - {} - ); - - expect(response.statusCode).toEqual(mockResponse.statusCode); - expect(response.headers).toBeDefined(); - expect(response.headers).toMatchObject(mockResponse.headers); - expect(inputBodySpy.mock.calls.length).toBeTruthy(); - });*/ - - it("rejects if the request encounters an error", async () => { - const mockResponse = { - statusCode: 200, - headers: {}, - body: "test", - }; - mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); - const nodeHttpHandler = new NodeHttpHandler(); - - await expect( - nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "fake:", // trigger a request error - path: "/", - headers: {}, - }), - {} - ) - ).rejects.toHaveProperty("message"); - }); - - it("will not make request if already aborted", async () => { - const mockResponse = { - statusCode: 200, - headers: {}, - body: "test", - }; - mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); - const spy = jest.spyOn(https, "request").mockImplementationOnce(() => { - const calls = spy.mock.calls; - const currentIndex = calls.length - 1; - return https.request(calls[currentIndex][0], calls[currentIndex][1]); - }); - // clear data held from previous tests - spy.mockClear(); - const nodeHttpHandler = new NodeHttpHandler(); - - await expect( - nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {}, - }), - { - abortSignal: { - aborted: true, - onabort: null, - }, - } - ) - ).rejects.toHaveProperty("name", "AbortError"); - - expect(spy.mock.calls.length).toBe(0); - }); - - it(`won't throw uncatchable error in writeRequestBody`, async () => { - const nodeHttpHandler = new NodeHttpHandler(); - - await expect( - nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {}, - body: {}, - }) - ) - ).rejects.toHaveProperty("name", "TypeError"); - }); - - it("will destroy the request when aborted", async () => { - const mockResponse = { - statusCode: 200, - headers: {}, - body: "test", - }; - mockHttpsServer.addListener("request", createResponseFunction(mockResponse)); - let httpRequest: http.ClientRequest; - let reqDestroySpy: any; - const spy = jest.spyOn(https, "request").mockImplementationOnce(() => { - const calls = spy.mock.calls; - const currentIndex = calls.length - 1; - httpRequest = https.request(calls[currentIndex][0], calls[currentIndex][1]); - reqDestroySpy = jest.spyOn(httpRequest, "destroy"); - return httpRequest; - }); - const nodeHttpHandler = new NodeHttpHandler(); - const abortController = new AbortController(); - - setTimeout(() => { - abortController.abort(); - }, 0); - - await expect( - nodeHttpHandler.handle( - new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpsServer.address() as AddressInfo).port, - protocol: "https:", - path: "/", - headers: {}, - }), - { - abortSignal: abortController.signal, - } - ) - ).rejects.toHaveProperty("name", "AbortError"); - - expect(reqDestroySpy.mock.calls.length).toBe(1); }); }); @@ -679,77 +201,13 @@ describe("NodeHttpHandler", () => { }); }); - describe("configs", () => { - const mockResponse = { - statusCode: 200, - statusText: "OK", - headers: {}, - body: "test", - }; - - let mockHttpServer: HttpServer; - let request: HttpRequest; - - beforeAll(() => { - mockHttpServer = createMockHttpServer().listen(54320); - request = new HttpRequest({ - hostname: "localhost", - method: "GET", - port: (mockHttpServer.address() as AddressInfo).port, - protocol: "http:", - path: "/", - headers: {}, - }); - }); - - afterEach(() => { - mockHttpServer.removeAllListeners("request"); - mockHttpServer.removeAllListeners("checkContinue"); - }); - - afterAll(() => { - mockHttpServer.close(); - }); - - it("put HttpClientConfig", async () => { - mockHttpServer.addListener("request", createResponseFunction(mockResponse)); - - const nodeHttpHandler = new NodeHttpHandler(); - const requestTimeout = 200; - - nodeHttpHandler.updateHttpClientConfig("requestTimeout", requestTimeout); - - await nodeHttpHandler.handle(request, {}); - - expect(nodeHttpHandler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); - }); - - it("update existing HttpClientConfig", async () => { - mockHttpServer.addListener("request", createResponseFunction(mockResponse)); - - const nodeHttpHandler = new NodeHttpHandler({ requestTimeout: 200 }); - const requestTimeout = 300; - - nodeHttpHandler.updateHttpClientConfig("requestTimeout", requestTimeout); - - await nodeHttpHandler.handle(request, {}); - - expect(nodeHttpHandler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); - }); - - it("httpHandlerConfigs returns empty object if handle is not called", async () => { - const nodeHttpHandler = new NodeHttpHandler(); - expect(nodeHttpHandler.httpHandlerConfigs()).toEqual({}); - }); - }); - describe("checkSocketUsage", () => { beforeEach(() => { - jest.spyOn(console, "warn").mockImplementation(jest.fn()); + vi.spyOn(console, "warn").mockImplementation(vi.fn() as any); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("warns when socket exhaustion is detected", async () => { diff --git a/packages/node-http-handler/src/node-http-handler.ts b/packages/node-http-handler/src/node-http-handler.ts index 28bfa969b55..8c5f2d14339 100644 --- a/packages/node-http-handler/src/node-http-handler.ts +++ b/packages/node-http-handler/src/node-http-handler.ts @@ -10,6 +10,7 @@ import { getTransformedHeaders } from "./get-transformed-headers"; import { setConnectionTimeout } from "./set-connection-timeout"; import { setSocketKeepAlive } from "./set-socket-keep-alive"; import { setSocketTimeout } from "./set-socket-timeout"; +import { timing } from "./timing"; import { writeRequestBody } from "./write-request-body"; export { NodeHttpHandlerOptions }; @@ -154,12 +155,12 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf const resolve = async (arg: { response: HttpResponse }) => { await writeRequestBodyPromise; - timeouts.forEach(clearTimeout); + timeouts.forEach(timing.clearTimeout); _resolve(arg); }; const reject = async (arg: unknown) => { await writeRequestBodyPromise; - timeouts.forEach(clearTimeout); + timeouts.forEach(timing.clearTimeout); _reject(arg); }; @@ -182,7 +183,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf // If the request is taking a long time, check socket usage and potentially warn. // This warning will be cancelled if the request resolves. timeouts.push( - setTimeout( + timing.setTimeout( () => { this.socketWarningTimestamp = NodeHttpHandler.checkSocketUsage( agent, @@ -287,7 +288,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf } writeRequestBodyPromise = writeRequestBody(req, request, this.config.requestTimeout).catch((e) => { - timeouts.forEach(clearTimeout); + timeouts.forEach(timing.clearTimeout); return _reject(e); }); }); diff --git a/packages/node-http-handler/src/node-http2-connection-manager.ts b/packages/node-http-handler/src/node-http2-connection-manager.ts index 76f35383c15..3e3f669a49b 100644 --- a/packages/node-http-handler/src/node-http2-connection-manager.ts +++ b/packages/node-http-handler/src/node-http2-connection-manager.ts @@ -109,7 +109,7 @@ export class NodeHttp2ConnectionManager implements ConnectionManager { let nodeH2Handler: NodeHttp2Handler; const protocol = "http:"; const hostname = "localhost"; - const port = 45321; + let port1: number = 0; + let port2: number = 0; + let port3: number = 0; + let port4: number = 0; + let mockH2Server: any = undefined; - let mockH2Servers: Record = {}; + const mockH2Servers: Record = {}; - const authority = `${protocol}//${hostname}:${port}/`; + let authority: string; const getMockReqOptions = () => ({ protocol, hostname, - port, + port: port1, method: "GET", path: "/", headers: {}, @@ -34,24 +41,29 @@ describe(NodeHttp2Handler.name, () => { body: "test", }; - beforeEach(() => { - mockH2Servers = { - 45321: createMockHttp2Server().listen(port), - 45322: createMockHttp2Server().listen(port + 1), - 45323: createMockHttp2Server().listen(port + 2), - 45324: createMockHttp2Server().listen(port + 3), - }; - mockH2Server = mockH2Servers[port]; + beforeEach(async () => { + for (let i = 0; i < 4; ++i) { + const port = await getPort({ port: portNumbers(45_341, 50_000) }); + mockH2Servers[port] = createMockHttp2Server().listen(port); + } + + [port1, port2, port3, port4] = Object.keys(mockH2Servers).map(Number); + authority = `${protocol}//${hostname}:${port1}/`; + + mockH2Server = mockH2Servers[port1]; mockH2Server.on("request", createResponseFunction(mockResponse)); }); afterEach(() => { mockH2Server.removeAllListeners("request"); - jest.clearAllMocks(); + vi.clearAllMocks(); for (const p in mockH2Servers) { mockH2Servers[p].removeAllListeners("request"); mockH2Servers[p].close(); } + Object.keys(mockH2Servers).forEach((key) => { + delete mockH2Servers[key]; + }); }); describe.each([ @@ -62,18 +74,18 @@ describe(NodeHttp2Handler.name, () => { ])("without options in constructor parameter of %s", (_, option) => { let createdSessions!: ClientHttp2Session[]; const connectReal = http2.connect; - let connectSpy!: jest.SpiedFunction; + let connectSpy!: typeof http2.connect; beforeEach(() => { createdSessions = []; - connectSpy = jest.spyOn(http2, "connect").mockImplementation((...args) => { - const session = connectReal(...args); - jest.spyOn(session, "ref"); - jest.spyOn(session, "unref"); - jest.spyOn(session, "settings"); + connectSpy = vi.spyOn(http2, "connect").mockImplementation((...args: any[]) => { + const session = connectReal(args[0], args[1]); + vi.spyOn(session, "ref"); + vi.spyOn(session, "unref"); + vi.spyOn(session, "settings"); createdSessions.push(session); return session; - }); + }) as any; nodeH2Handler = new NodeHttp2Handler(option); }); @@ -123,7 +135,7 @@ describe(NodeHttp2Handler.name, () => { }); it("is one if multiple requests are made on same URL", async () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); // Make two requests. const { response: response1 } = await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); @@ -139,12 +151,11 @@ describe(NodeHttp2Handler.name, () => { }); it("is many if requests are made on different URLs", async () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); // Make first request on default URL. const { response: response1 } = await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); - const port2 = port + 1; const mockH2Server2 = mockH2Servers[port2]; mockH2Server2.on("request", createResponseFunction(mockResponse)); @@ -156,7 +167,7 @@ describe(NodeHttp2Handler.name, () => { const authorityPrefix = `${protocol}//${hostname}`; expect(connectSpy).toHaveBeenCalledTimes(2); - expect(connectSpy).toHaveBeenNthCalledWith(1, `${authorityPrefix}:${port}/`); + expect(connectSpy).toHaveBeenNthCalledWith(1, `${authorityPrefix}:${port1}/`); expect(connectSpy).toHaveBeenNthCalledWith(2, `${authorityPrefix}:${port2}/`); mockH2Server2.close(); @@ -172,7 +183,6 @@ describe(NodeHttp2Handler.name, () => { describe("errors", () => { const UNEXPECTEDLY_CLOSED_REGEX = /closed|destroy|cancel|did not get a response/i; it("handles goaway frames", async () => { - const port3 = port + 2; const mockH2Server3 = mockH2Servers[port3]; let establishedConnections = 0; let numRequests = 0; @@ -183,7 +193,7 @@ describe(NodeHttp2Handler.name, () => { // to simulate an unlikely error mode. numRequests += 1; if (shouldSendGoAway) { - request.session.goaway(constants.NGHTTP2_PROTOCOL_ERROR); + request.session!.goaway(constants.NGHTTP2_PROTOCOL_ERROR); } }); mockH2Server3.on("connection", () => { @@ -250,16 +260,17 @@ describe(NodeHttp2Handler.name, () => { }); it.each([ - ["destroy", port + 2], - ["close", port + 3], - ])("handles servers calling connections %s", async (func, port) => { + ["destroy", 1], + ["close", 2], + ])("handles servers calling connections %s", async (func, portIndex) => { + const port = [port1, port2, port3, port4][portIndex]; const mockH2Server4 = mockH2Servers[port]; let establishedConnections = 0; let numRequests = 0; mockH2Server4.on("stream", (request: Http2Stream) => { numRequests += 1; - request.session[func](); + request.session![func](); }); mockH2Server4.on("connection", () => { establishedConnections += 1; @@ -337,7 +348,7 @@ describe(NodeHttp2Handler.name, () => { // @ts-ignore: access private property const session: ClientHttp2Session = nodeH2Handler.connectionManager.sessionCache.get(authority).sessions[0]; - const requestSpy = jest.spyOn(session, "request"); + const requestSpy = vi.spyOn(session, "request"); await expect( nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), { @@ -479,6 +490,7 @@ describe(NodeHttp2Handler.name, () => { ["static object", { maxConcurrentStreams: 3 }], ])("verify session settings' maxConcurrentStreams", async (_, options: NodeHttp2HandlerOptions) => { nodeH2Handler = new NodeHttp2Handler(options); + await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); // @ts-ignore: access private property @@ -486,7 +498,6 @@ describe(NodeHttp2Handler.name, () => { if (options.maxConcurrentStreams) { expect(session.localSettings.maxConcurrentStreams).toBe(options.maxConcurrentStreams); - expect(session.settings).toHaveBeenCalled(); } else { expect(session.localSettings.maxConcurrentStreams).toBe(4294967295); } @@ -496,13 +507,15 @@ describe(NodeHttp2Handler.name, () => { let error: Error | undefined = undefined; try { nodeH2Handler = new NodeHttp2Handler({ maxConcurrentStreams: -1 }); - await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); + + const options = getMockReqOptions(); + await nodeH2Handler.handle(new HttpRequest(options), {}); } catch (e) { error = e; } expect(error).toBeDefined(); - expect(error!.message).toEqual('Invalid value for setting "maxConcurrentStreams": -1'); + expect(error!.message).toEqual("maxConcurrentStreams must be greater than zero."); }); }); @@ -516,11 +529,11 @@ describe(NodeHttp2Handler.name, () => { const fakeRstCode = 1; // @ts-ignore: fake result code fakeStream.rstCode = fakeRstCode; - jest.spyOn(session, "request").mockImplementation(() => fakeStream); + vi.spyOn(session, "request").mockImplementation(() => fakeStream); // @ts-ignore: access private property nodeH2Handler.connectionManager.sessionCache.set(authority, new NodeHttp2ConnectionPool([session])); // Delay response so that onabort is called earlier - setTimeout(() => { + timing.setTimeout(() => { fakeStream.emit("aborted"); }, 0); @@ -537,11 +550,11 @@ describe(NodeHttp2Handler.name, () => { // @ts-ignore: access private property const session: ClientHttp2Session = nodeH2Handler.connectionManager.sessionCache.get(authority).sessions[0]; const fakeStream = new Duplex() as ClientHttp2Stream; - jest.spyOn(session, "request").mockImplementation(() => fakeStream); + vi.spyOn(session, "request").mockImplementation(() => fakeStream); // @ts-ignore: access private property nodeH2Handler.connectionManager.sessionCache.set(authority, new NodeHttp2ConnectionPool([session])); // Delay response so that onabort is called earlier - setTimeout(() => { + timing.setTimeout(() => { fakeStream.emit("frameError", "TYPE", "CODE", "ID"); }, 0); @@ -561,12 +574,12 @@ describe(NodeHttp2Handler.name, () => { describe("number calls to http2.connect", () => { it("is zero on initialization", () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); expect(connectSpy).not.toHaveBeenCalled(); }); it("is one when request is made", async () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); // Make single request. await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); @@ -575,7 +588,7 @@ describe(NodeHttp2Handler.name, () => { }); it("is many if multiple requests are made on same URL", async () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); // Make two requests. await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); @@ -587,12 +600,11 @@ describe(NodeHttp2Handler.name, () => { }); it("is many if requests are made on different URLs", async () => { - const connectSpy = jest.spyOn(http2, "connect"); + const connectSpy = vi.spyOn(http2, "connect"); // Make first request on default URL. await nodeH2Handler.handle(new HttpRequest(getMockReqOptions()), {}); - const port2 = port + 1; const mockH2Server2 = mockH2Servers[port2]; mockH2Server2.on("request", createResponseFunction(mockResponse)); @@ -601,7 +613,7 @@ describe(NodeHttp2Handler.name, () => { const authorityPrefix = `${protocol}//${hostname}`; expect(connectSpy).toHaveBeenCalledTimes(2); - expect(connectSpy).toHaveBeenNthCalledWith(1, `${authorityPrefix}:${port}/`); + expect(connectSpy).toHaveBeenNthCalledWith(1, `${authorityPrefix}:${port1}/`); expect(connectSpy).toHaveBeenNthCalledWith(2, `${authorityPrefix}:${port2}/`); mockH2Server2.close(); }); @@ -626,68 +638,78 @@ describe(NodeHttp2Handler.name, () => { }); }); - it("sends the request to the correct url", async () => { - const server = createMockHttp2Server(); - server.on("request", (request, response) => { - expect(request.url).toBe("http://foo:bar@localhost/foo/bar?foo=bar#foo"); - response.statusCode = 200; + describe("server", () => { + let server: Http2Server; + + beforeEach(async () => { + const port = await getPort({ port: portNumbers(45_321, 50_000) }); + server = createMockHttp2Server().listen(port); }); - const handler = new NodeHttp2Handler({}); - await handler.handle({ - ...getMockReqOptions(), - username: "foo", - password: "bar", - path: "/foo/bar", - query: { foo: "bar" }, - fragment: "foo", - } as any); - handler.destroy(); - }); - it("put HttpClientConfig", async () => { - const server = createMockHttp2Server(); - server.on("request", (request, response) => { - expect(request.url).toBe("http://foo:bar@localhost/"); - response.statusCode = 200; + afterEach(() => { + server.close(); }); - const handler = new NodeHttp2Handler({}); - const requestTimeout = 200; + it("sends the request to the correct url", async () => { + server.on("request", (request, response) => { + expect(request.url).toBe("http://foo:bar@localhost/foo/bar?foo=bar#foo"); + response.statusCode = 200; + }); + const handler = new NodeHttp2Handler({}); + await handler.handle({ + ...getMockReqOptions(), + username: "foo", + password: "bar", + path: "/foo/bar", + query: { foo: "bar" }, + fragment: "foo", + } as any); + handler.destroy(); + }); - handler.updateHttpClientConfig("requestTimeout", requestTimeout); + it("put HttpClientConfig", async () => { + server.on("request", (request, response) => { + expect(request.url).toBe("http://foo:bar@localhost/"); + response.statusCode = 200; + }); + const handler = new NodeHttp2Handler({}); - await handler.handle({ - ...getMockReqOptions(), - username: "foo", - password: "bar", - path: "/", - } as any); - handler.destroy(); + const requestTimeout = 200; - expect(handler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); - }); + handler.updateHttpClientConfig("requestTimeout", requestTimeout); + + await handler.handle({ + ...getMockReqOptions(), + username: "foo", + password: "bar", + path: "/", + } as any); + handler.destroy(); - it("update existing HttpClientConfig", async () => { - const server = createMockHttp2Server(); - server.on("request", (request, response) => { - expect(request.url).toBe("http://foo:bar@localhost/"); - response.statusCode = 200; + expect(handler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); }); - const handler = new NodeHttp2Handler({ requestTimeout: 200 }); - const requestTimeout = 300; + it("update existing HttpClientConfig", async () => { + server.on("request", (request, response) => { + expect(request.url).toBe("http://foo:bar@localhost/"); + response.statusCode = 200; + }); + const handler = new NodeHttp2Handler({ requestTimeout: 200 }); - handler.updateHttpClientConfig("requestTimeout", requestTimeout); + const requestTimeout = 300; - await handler.handle({ - ...getMockReqOptions(), - username: "foo", - password: "bar", - path: "/", - } as any); - handler.destroy(); + handler.updateHttpClientConfig("requestTimeout", requestTimeout); - expect(handler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); + await handler.handle({ + ...getMockReqOptions(), + username: "foo", + password: "bar", + path: "/", + } as any); + handler.destroy(); + + expect(handler.httpHandlerConfigs().requestTimeout).toEqual(requestTimeout); + }); }); it("httpHandlerConfigs returns empty object if handle is not called", async () => { diff --git a/packages/node-http-handler/src/server.mock.ts b/packages/node-http-handler/src/server.mock.ts index a06b9016d18..a904cd0034e 100644 --- a/packages/node-http-handler/src/server.mock.ts +++ b/packages/node-http-handler/src/server.mock.ts @@ -6,6 +6,8 @@ import { createServer as createHttpsServer, Server as HttpsServer } from "https" import { join } from "path"; import { Readable } from "stream"; +import { timing } from "./timing"; + const fixturesDir = join(__dirname, "..", "fixtures"); const setResponseHeaders = (response: ServerResponse, headers: HeaderBag) => { @@ -25,6 +27,9 @@ const setResponseBody = (response: ServerResponse, body: string | NodeJsRuntimeB export const createResponseFunction = (httpResp: HttpResponse) => (request: IncomingMessage, response: ServerResponse) => { response.statusCode = httpResp.statusCode; + if (httpResp.reason) { + response.statusMessage = httpResp.reason; + } setResponseHeaders(response, httpResp.headers); setResponseBody(response, httpResp.body); }; @@ -32,14 +37,17 @@ export const createResponseFunction = export const createResponseFunctionWithDelay = (httpResp: HttpResponse, delay: number) => (request: IncomingMessage, response: ServerResponse) => { response.statusCode = httpResp.statusCode; + if (httpResp.reason) { + response.statusMessage = httpResp.reason; + } setResponseHeaders(response, httpResp.headers); - setTimeout(() => setResponseBody(response, httpResp.body), delay); + timing.setTimeout(() => setResponseBody(response, httpResp.body), delay); }; export const createContinueResponseFunction = (httpResp: HttpResponse) => (request: IncomingMessage, response: ServerResponse) => { response.writeContinue(); - setTimeout(() => { + timing.setTimeout(() => { createResponseFunction(httpResp)(request, response); }, 100); }; diff --git a/packages/node-http-handler/src/set-connection-timeout.spec.ts b/packages/node-http-handler/src/set-connection-timeout.spec.ts index 015c9cc3c36..6d226fc5a78 100644 --- a/packages/node-http-handler/src/set-connection-timeout.spec.ts +++ b/packages/node-http-handler/src/set-connection-timeout.spec.ts @@ -1,14 +1,25 @@ +import EventEmitter from "events"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { setConnectionTimeout } from "./set-connection-timeout"; +import { timing } from "./timing"; describe("setConnectionTimeout", () => { - const reject = jest.fn(); + const reject = vi.fn(); const clientRequest: any = { - on: jest.fn(), - destroy: jest.fn(), + on: vi.fn(), + destroy: vi.fn(), }; + vi.spyOn(timing, "setTimeout").mockImplementation(((fn: Function, ms: number) => { + return setTimeout(fn, ms); + }) as any); + vi.spyOn(timing, "clearTimeout").mockImplementation(((timer: any) => { + return clearTimeout(timer); + }) as any); + beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("will not attach listeners if timeout is 0", () => { @@ -25,38 +36,37 @@ describe("setConnectionTimeout", () => { const timeoutInMs = 100; const mockSocket = { connecting: true, - on: jest.fn(), + on: vi.fn(), }; beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); - setConnectionTimeout(clientRequest, reject, timeoutInMs); + vi.useFakeTimers(); + vi.clearAllMocks(); }); afterEach(() => { - jest.advanceTimersByTime(10000); - jest.useRealTimers(); + vi.advanceTimersByTime(10000); + vi.useRealTimers(); }); it("attaches listener", () => { + setConnectionTimeout(clientRequest, reject, timeoutInMs); expect(clientRequest.on).toHaveBeenCalledTimes(1); expect(clientRequest.on).toHaveBeenCalledWith("socket", expect.any(Function)); }); it("doesn't set timeout if socket is already connected", () => { - clientRequest.on.mock.calls[0][1]({ - ...mockSocket, - connecting: false, - }); + setConnectionTimeout(clientRequest, reject, timeoutInMs); expect(mockSocket.on).not.toHaveBeenCalled(); - expect(setTimeout).toHaveBeenCalled(); + expect(timing.setTimeout).toHaveBeenCalled(); expect(reject).not.toHaveBeenCalled(); }); - it("rejects and aborts request if socket isn't connected by timeout", () => { + it("rejects and aborts request if socket isn't connected by timeout", async () => { + setConnectionTimeout(clientRequest, reject, timeoutInMs); clientRequest.on.mock.calls[0][1](mockSocket); - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), timeoutInMs); + expect(timing.setTimeout).toHaveBeenCalledTimes(1); + expect(timing.setTimeout).toHaveBeenCalledWith(expect.any(Function), timeoutInMs); expect(mockSocket.on).toHaveBeenCalledTimes(1); expect(mockSocket.on).toHaveBeenCalledWith("connect", expect.any(Function)); @@ -64,7 +74,7 @@ describe("setConnectionTimeout", () => { expect(reject).not.toHaveBeenCalled(); // Fast-forward until timer has been executed. - jest.advanceTimersByTime(timeoutInMs); + vi.advanceTimersByTime(timeoutInMs); expect(clientRequest.destroy).toHaveBeenCalledTimes(1); expect(reject).toHaveBeenCalledTimes(1); expect(reject).toHaveBeenCalledWith( @@ -75,36 +85,47 @@ describe("setConnectionTimeout", () => { }); it("calls socket operations directly if socket is available", async () => { + setConnectionTimeout(clientRequest, reject, timeoutInMs); const request = { - on: jest.fn(), + on: vi.fn(), socket: { - on: jest.fn(), + on: vi.fn(), connecting: true, }, destroy() {}, } as any; setConnectionTimeout(request, () => {}, 1); - jest.runAllTimers(); + vi.runAllTimers(); expect(request.socket.on).toHaveBeenCalled(); expect(request.on).not.toHaveBeenCalled(); }); it("clears timeout if socket gets connected", () => { - clientRequest.on.mock.calls[0][1](mockSocket); + const socket = new EventEmitter() as any; + socket.connecting = true; + + setConnectionTimeout( + { + ...clientRequest, + socket, + }, + reject, + timeoutInMs + ); expect(clientRequest.destroy).not.toHaveBeenCalled(); expect(reject).not.toHaveBeenCalled(); - expect(clearTimeout).not.toHaveBeenCalled(); + expect(timing.clearTimeout).not.toHaveBeenCalled(); // Fast-forward for half the amount of time and call connect callback to clear timer. - jest.advanceTimersByTime(timeoutInMs / 2); - mockSocket.on.mock.calls[0][1](); + vi.advanceTimersByTime(timeoutInMs / 2); + socket.emit("connect"); - expect(clearTimeout).toHaveBeenCalled(); + expect(timing.clearTimeout).toHaveBeenCalled(); // Fast-forward until timer has been executed. - jest.runAllTimers(); + vi.runAllTimers(); expect(clientRequest.destroy).not.toHaveBeenCalled(); expect(reject).not.toHaveBeenCalled(); }); diff --git a/packages/node-http-handler/src/set-connection-timeout.ts b/packages/node-http-handler/src/set-connection-timeout.ts index fa21712872b..7eed13c90cb 100644 --- a/packages/node-http-handler/src/set-connection-timeout.ts +++ b/packages/node-http-handler/src/set-connection-timeout.ts @@ -1,5 +1,7 @@ import { ClientRequest } from "http"; +import { timing } from "./timing"; + const DEFER_EVENT_LISTENER_TIME = 1000; export const setConnectionTimeout = ( @@ -13,7 +15,7 @@ export const setConnectionTimeout = ( const registerTimeout = (offset: number) => { // Throw a connecting timeout error unless a connection is made within time. - const timeoutId = setTimeout(() => { + const timeoutId = timing.setTimeout(() => { request.destroy(); reject( Object.assign(new Error(`Socket timed out without establishing a connection within ${timeoutInMs} ms`), { @@ -25,10 +27,10 @@ export const setConnectionTimeout = ( const doWithSocket = (socket: typeof request.socket) => { if (socket?.connecting) { socket.on("connect", () => { - clearTimeout(timeoutId); + timing.clearTimeout(timeoutId); }); } else { - clearTimeout(timeoutId); + timing.clearTimeout(timeoutId); } }; @@ -44,5 +46,5 @@ export const setConnectionTimeout = ( return 0; } - return setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME); + return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME); }; diff --git a/packages/node-http-handler/src/set-socket-keep-alive.spec.ts b/packages/node-http-handler/src/set-socket-keep-alive.spec.ts index 170f7fb862d..0666cc13f72 100644 --- a/packages/node-http-handler/src/set-socket-keep-alive.spec.ts +++ b/packages/node-http-handler/src/set-socket-keep-alive.spec.ts @@ -1,6 +1,7 @@ import { EventEmitter } from "events"; import { ClientRequest } from "http"; import { Socket } from "net"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { setSocketKeepAlive } from "./set-socket-keep-alive"; @@ -16,7 +17,7 @@ describe("setSocketKeepAlive", () => { it("should set keepAlive to true", () => { setSocketKeepAlive(request, { keepAlive: true }, 0); - const setKeepAliveSpy = jest.spyOn(socket, "setKeepAlive"); + const setKeepAliveSpy = vi.spyOn(socket, "setKeepAlive"); request.emit("socket", socket); expect(setKeepAliveSpy).toHaveBeenCalled(); @@ -27,7 +28,7 @@ describe("setSocketKeepAlive", () => { const initialDelay = 5 * 1000; setSocketKeepAlive(request, { keepAlive: true, keepAliveMsecs: initialDelay }, 0); - const setKeepAliveSpy = jest.spyOn(socket, "setKeepAlive"); + const setKeepAliveSpy = vi.spyOn(socket, "setKeepAlive"); request.emit("socket", socket); expect(setKeepAliveSpy).toHaveBeenCalled(); @@ -37,7 +38,7 @@ describe("setSocketKeepAlive", () => { it("should not set keepAlive at all when keepAlive is false", () => { setSocketKeepAlive(request, { keepAlive: false }, 0); - const setKeepAliveSpy = jest.spyOn(socket, "setKeepAlive"); + const setKeepAliveSpy = vi.spyOn(socket, "setKeepAlive"); request.emit("socket", socket); expect(setKeepAliveSpy).not.toHaveBeenCalled(); @@ -45,9 +46,9 @@ describe("setSocketKeepAlive", () => { it("calls socket operations directly if socket is available", async () => { const request = { - on: jest.fn(), + on: vi.fn(), socket: { - setKeepAlive: jest.fn(), + setKeepAlive: vi.fn(), }, } as any; setSocketKeepAlive(request, { keepAlive: true, keepAliveMsecs: 1000 }, 0); diff --git a/packages/node-http-handler/src/set-socket-keep-alive.ts b/packages/node-http-handler/src/set-socket-keep-alive.ts index 02ce6695369..bfdc2ea365d 100644 --- a/packages/node-http-handler/src/set-socket-keep-alive.ts +++ b/packages/node-http-handler/src/set-socket-keep-alive.ts @@ -1,5 +1,7 @@ import { ClientRequest } from "http"; +import { timing } from "./timing"; + const DEFER_EVENT_LISTENER_TIME = 3000; export interface SocketKeepAliveOptions { @@ -31,5 +33,5 @@ export const setSocketKeepAlive = ( return 0; } - return setTimeout(registerListener, deferTimeMs); + return timing.setTimeout(registerListener, deferTimeMs); }; diff --git a/packages/node-http-handler/src/set-socket-timeout.spec.ts b/packages/node-http-handler/src/set-socket-timeout.spec.ts index 30fe30fd183..4f46371bac0 100644 --- a/packages/node-http-handler/src/set-socket-timeout.spec.ts +++ b/packages/node-http-handler/src/set-socket-timeout.spec.ts @@ -1,39 +1,49 @@ +import { afterAll, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { setSocketTimeout } from "./set-socket-timeout"; +import { timing } from "./timing"; describe("setSocketTimeout", () => { const clientRequest: any = { - destroy: jest.fn(), - setTimeout: jest.fn(), + destroy: vi.fn(), + setTimeout: vi.fn(), }; + vi.spyOn(timing, "setTimeout").mockImplementation(((fn: Function, ms: number) => { + return setTimeout(fn, ms); + }) as any); + vi.spyOn(timing, "clearTimeout").mockImplementation(((timer: any) => { + return clearTimeout(timer); + }) as any); + beforeEach(() => { - jest.clearAllMocks(); - jest.useFakeTimers(); + vi.clearAllMocks(); + vi.useFakeTimers(); }); afterAll(() => { - jest.clearAllMocks(); - jest.useRealTimers(); + vi.clearAllMocks(); + vi.useRealTimers(); }); it(`sets the request's timeout if provided`, () => { - setSocketTimeout(clientRequest, jest.fn(), 100); + setSocketTimeout(clientRequest, vi.fn(), 100); expect(clientRequest.setTimeout).toHaveBeenCalledTimes(1); expect(clientRequest.setTimeout).toHaveBeenLastCalledWith(100, expect.any(Function)); }); it(`sets the request's timeout to 0 if not provided`, async () => { - setSocketTimeout(clientRequest, jest.fn()); + setSocketTimeout(clientRequest, vi.fn()); - jest.runAllTimers(); + vi.runAllTimers(); expect(clientRequest.setTimeout).toHaveBeenCalledTimes(1); expect(clientRequest.setTimeout).toHaveBeenLastCalledWith(0, expect.any(Function)); }); it(`destroys the request on timeout`, () => { - setSocketTimeout(clientRequest, jest.fn(), 1); + setSocketTimeout(clientRequest, vi.fn(), 1); expect(clientRequest.destroy).not.toHaveBeenCalled(); // call setTimeout callback @@ -42,7 +52,7 @@ describe("setSocketTimeout", () => { }); it(`rejects on timeout with a TimeoutError`, () => { - const reject = jest.fn(); + const reject = vi.fn(); const timeoutInMs = 100; setSocketTimeout(clientRequest, reject, timeoutInMs); diff --git a/packages/node-http-handler/src/set-socket-timeout.ts b/packages/node-http-handler/src/set-socket-timeout.ts index 78f79a4f43a..aec66c37c99 100644 --- a/packages/node-http-handler/src/set-socket-timeout.ts +++ b/packages/node-http-handler/src/set-socket-timeout.ts @@ -1,5 +1,7 @@ import { ClientRequest } from "http"; +import { timing } from "./timing"; + const DEFER_EVENT_LISTENER_TIME = 3000; export const setSocketTimeout = ( @@ -20,7 +22,7 @@ export const setSocketTimeout = ( return 0; } - return setTimeout( + return timing.setTimeout( registerTimeout.bind(null, timeoutInMs === 0 ? 0 : DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME ); diff --git a/packages/node-http-handler/src/stream-collector/collector.spec.ts b/packages/node-http-handler/src/stream-collector/collector.spec.ts index cdcb1c612cd..eda7d8064ec 100644 --- a/packages/node-http-handler/src/stream-collector/collector.spec.ts +++ b/packages/node-http-handler/src/stream-collector/collector.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { Collector } from "./collector"; describe("Collector", () => { diff --git a/packages/node-http-handler/src/stream-collector/index.spec.ts b/packages/node-http-handler/src/stream-collector/index.spec.ts index fb958f0f6ea..a855a310366 100644 --- a/packages/node-http-handler/src/stream-collector/index.spec.ts +++ b/packages/node-http-handler/src/stream-collector/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { streamCollector } from "./index"; import { ReadFromBuffers } from "./readable.mock"; diff --git a/packages/node-http-handler/src/timing.ts b/packages/node-http-handler/src/timing.ts new file mode 100644 index 00000000000..f78f530bc45 --- /dev/null +++ b/packages/node-http-handler/src/timing.ts @@ -0,0 +1,8 @@ +/** + * @internal + * For test spies. + */ +export const timing = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, +}; diff --git a/packages/node-http-handler/src/write-request-body.ts b/packages/node-http-handler/src/write-request-body.ts index b17de80121c..7c3e9bf72ab 100644 --- a/packages/node-http-handler/src/write-request-body.ts +++ b/packages/node-http-handler/src/write-request-body.ts @@ -3,6 +3,8 @@ import { ClientRequest } from "http"; import { ClientHttp2Stream } from "http2"; import { Readable } from "stream"; +import { timing } from "./timing"; + const MIN_WAIT_TIME = 1000; /** @@ -26,16 +28,16 @@ export async function writeRequestBody( if (expect === "100-continue") { await Promise.race([ new Promise((resolve) => { - timeoutId = Number(setTimeout(resolve, Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs))); + timeoutId = Number(timing.setTimeout(resolve, Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs))); }), new Promise((resolve) => { httpRequest.on("continue", () => { - clearTimeout(timeoutId); + timing.clearTimeout(timeoutId); resolve(); }); httpRequest.on("error", () => { hasError = true; - clearTimeout(timeoutId); + timing.clearTimeout(timeoutId); // this handler does not reject with the error // because there is already an error listener // on the request in node-http-handler diff --git a/packages/node-http-handler/vitest.config.ts b/packages/node-http-handler/vitest.config.ts new file mode 100644 index 00000000000..58d980445e6 --- /dev/null +++ b/packages/node-http-handler/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/property-provider/jest.config.js b/packages/property-provider/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/property-provider/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/property-provider/package.json b/packages/property-provider/package.json index 2c5d97ee51a..c34be33b52e 100644 --- a/packages/property-provider/package.json +++ b/packages/property-provider/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/property-provider/src/CredentialsProviderError.spec.ts b/packages/property-provider/src/CredentialsProviderError.spec.ts index f3deda45d8b..42cd3a83951 100644 --- a/packages/property-provider/src/CredentialsProviderError.spec.ts +++ b/packages/property-provider/src/CredentialsProviderError.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { CredentialsProviderError } from "./CredentialsProviderError"; import { ProviderError } from "./ProviderError"; @@ -28,11 +30,11 @@ describe(CredentialsProviderError.name, () => { it("should use logger.debug if provided", () => { const logger = { - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - debug: jest.fn(), - trace: jest.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + debug: vi.fn(), + trace: vi.fn(), }; new CredentialsProviderError("PANIC", { logger }); diff --git a/packages/property-provider/src/ProviderError.spec.ts b/packages/property-provider/src/ProviderError.spec.ts index 0067fab17a0..9a83533c511 100644 --- a/packages/property-provider/src/ProviderError.spec.ts +++ b/packages/property-provider/src/ProviderError.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { ProviderError } from "./ProviderError"; describe(ProviderError.name, () => { diff --git a/packages/property-provider/src/TokenProviderError.spec.ts b/packages/property-provider/src/TokenProviderError.spec.ts index d6c06782065..3e5d97d9d84 100644 --- a/packages/property-provider/src/TokenProviderError.spec.ts +++ b/packages/property-provider/src/TokenProviderError.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { ProviderError } from "./ProviderError"; import { TokenProviderError } from "./TokenProviderError"; diff --git a/packages/property-provider/src/chain.spec.ts b/packages/property-provider/src/chain.spec.ts index 816e5a45b71..e5b4de4f65d 100644 --- a/packages/property-provider/src/chain.spec.ts +++ b/packages/property-provider/src/chain.spec.ts @@ -1,9 +1,11 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { chain } from "./chain"; import { ProviderError } from "./ProviderError"; -const resolveStatic = (staticValue: unknown) => jest.fn().mockResolvedValue(staticValue); -const rejectWithError = (errorMsg: string) => jest.fn().mockRejectedValue(new Error(errorMsg)); -const rejectWithProviderError = (errorMsg: string) => jest.fn().mockRejectedValue(new ProviderError(errorMsg)); +const resolveStatic = (staticValue: unknown) => vi.fn().mockResolvedValue(staticValue); +const rejectWithError = (errorMsg: string) => vi.fn().mockRejectedValue(new Error(errorMsg)); +const rejectWithProviderError = (errorMsg: string) => vi.fn().mockRejectedValue(new ProviderError(errorMsg)); describe("chain", () => { it("should distill many credential providers into one", async () => { @@ -90,7 +92,7 @@ describe("chain", () => { const expectedError = new ProviderError("ProviderError with tryNextLink set to false", false); const providers = [ rejectWithProviderError("Move along"), - jest.fn().mockRejectedValue(expectedError), + vi.fn().mockRejectedValue(expectedError), resolveStatic("foo"), ]; diff --git a/packages/property-provider/src/fromStatic.spec.ts b/packages/property-provider/src/fromStatic.spec.ts index 72f43d3d758..bd8e809357f 100644 --- a/packages/property-provider/src/fromStatic.spec.ts +++ b/packages/property-provider/src/fromStatic.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { fromStatic } from "./fromStatic"; describe("fromStatic", () => { diff --git a/packages/property-provider/src/memoize.spec.ts b/packages/property-provider/src/memoize.spec.ts index 904142ec601..3d6cbb631cd 100644 --- a/packages/property-provider/src/memoize.spec.ts +++ b/packages/property-provider/src/memoize.spec.ts @@ -1,16 +1,18 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { memoize } from "./memoize"; describe("memoize", () => { - let provider: jest.Mock; + let provider: vi.Mock; const mockReturn = "foo"; const repeatTimes = 10; beforeEach(() => { - provider = jest.fn().mockResolvedValue(mockReturn); + provider = vi.fn().mockResolvedValue(mockReturn); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("static memoization", () => { @@ -68,12 +70,12 @@ describe("memoize", () => { }); describe("refreshing memoization", () => { - let isExpired: jest.Mock; - let requiresRefresh: jest.Mock; + let isExpired: vi.Mock; + let requiresRefresh: vi.Mock; beforeEach(() => { - isExpired = jest.fn().mockReturnValue(true); - requiresRefresh = jest.fn().mockReturnValue(false); + isExpired = vi.fn().mockReturnValue(true); + requiresRefresh = vi.fn().mockReturnValue(false); }); describe("should not reinvoke the underlying provider while isExpired returns `false`", () => { diff --git a/packages/property-provider/vitest.config.ts b/packages/property-provider/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/property-provider/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/protocol-http/jest.config.js b/packages/protocol-http/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/protocol-http/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/protocol-http/package.json b/packages/protocol-http/package.json index acf817ccde9..a27d03a332d 100644 --- a/packages/protocol-http/package.json +++ b/packages/protocol-http/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/protocol-http/src/httpRequest.spec.ts b/packages/protocol-http/src/httpRequest.spec.ts index 0ecd6ec54fd..5c7c2680334 100644 --- a/packages/protocol-http/src/httpRequest.spec.ts +++ b/packages/protocol-http/src/httpRequest.spec.ts @@ -1,4 +1,5 @@ import { QueryParameterBag } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { HttpRequest, IHttpRequest } from "./httpRequest"; diff --git a/packages/protocol-http/src/isValidHostname.spec.ts b/packages/protocol-http/src/isValidHostname.spec.ts index aa280d55cf2..c1e82c2d3b4 100644 --- a/packages/protocol-http/src/isValidHostname.spec.ts +++ b/packages/protocol-http/src/isValidHostname.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isValidHostname } from "./isValidHostname"; describe("implementation selection", () => { diff --git a/packages/protocol-http/vitest.config.ts b/packages/protocol-http/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/protocol-http/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/querystring-builder/jest.config.js b/packages/querystring-builder/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/querystring-builder/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/querystring-parser/jest.config.js b/packages/querystring-parser/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/querystring-parser/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/querystring-parser/package.json b/packages/querystring-parser/package.json index be678ece6bd..f2020d06c9d 100644 --- a/packages/querystring-parser/package.json +++ b/packages/querystring-parser/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/querystring-parser/src/index.spec.ts b/packages/querystring-parser/src/index.spec.ts index 9091b89fdb5..3d8573e24eb 100644 --- a/packages/querystring-parser/src/index.spec.ts +++ b/packages/querystring-parser/src/index.spec.ts @@ -1,4 +1,5 @@ import { QueryParameterBag } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { parseQueryString } from "./"; diff --git a/packages/querystring-parser/vitest.config.ts b/packages/querystring-parser/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/querystring-parser/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/service-error-classification/jest.config.js b/packages/service-error-classification/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/service-error-classification/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/service-error-classification/package.json b/packages/service-error-classification/package.json index ba39f6c4e7a..d944a106f70 100644 --- a/packages/service-error-classification/package.json +++ b/packages/service-error-classification/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/service-error-classification/src/index.spec.ts b/packages/service-error-classification/src/index.spec.ts index ed83b6ac109..5daf462a175 100644 --- a/packages/service-error-classification/src/index.spec.ts +++ b/packages/service-error-classification/src/index.spec.ts @@ -1,4 +1,5 @@ import { RetryableTrait, SdkError } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { CLOCK_SKEW_ERROR_CODES, diff --git a/packages/service-error-classification/vitest.config.ts b/packages/service-error-classification/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/service-error-classification/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/shared-ini-file-loader/jest.config.js b/packages/shared-ini-file-loader/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/shared-ini-file-loader/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/shared-ini-file-loader/package.json b/packages/shared-ini-file-loader/package.json index 7b31fa0d33f..8f356085f29 100644 --- a/packages/shared-ini-file-loader/package.json +++ b/packages/shared-ini-file-loader/package.json @@ -23,7 +23,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/shared-ini-file-loader/src/getConfigData.spec.ts b/packages/shared-ini-file-loader/src/getConfigData.spec.ts index 401b13ffce5..17a4c3e1014 100644 --- a/packages/shared-ini-file-loader/src/getConfigData.spec.ts +++ b/packages/shared-ini-file-loader/src/getConfigData.spec.ts @@ -1,4 +1,5 @@ import { IniSectionType } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { getConfigData } from "./getConfigData"; import { CONFIG_PREFIX_SEPARATOR } from "./loadSharedConfigFiles"; diff --git a/packages/shared-ini-file-loader/src/getConfigFilepath.spec.ts b/packages/shared-ini-file-loader/src/getConfigFilepath.spec.ts index 5a9964db366..69758c140f7 100644 --- a/packages/shared-ini-file-loader/src/getConfigFilepath.spec.ts +++ b/packages/shared-ini-file-loader/src/getConfigFilepath.spec.ts @@ -1,10 +1,11 @@ import { join } from "path"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { ENV_CONFIG_PATH, getConfigFilepath } from "./getConfigFilepath"; import { getHomeDir } from "./getHomeDir"; -jest.mock("path"); -jest.mock("./getHomeDir"); +vi.mock("path"); +vi.mock("./getHomeDir"); describe(getConfigFilepath.name, () => { const mockSeparator = "/"; @@ -14,12 +15,12 @@ describe(getConfigFilepath.name, () => { const defaultConfigFilepath = `${mockHomeDir}/.aws/config`; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns configFilePath from default locations", () => { - (join as jest.Mock).mockImplementation((...args) => args.join(mockSeparator)); - (getHomeDir as jest.Mock).mockReturnValue(mockHomeDir); + vi.mocked(join).mockImplementation((...args) => args.join(mockSeparator)); + vi.mocked(getHomeDir).mockReturnValue(mockHomeDir); expect(getConfigFilepath()).toStrictEqual(defaultConfigFilepath); expect(getHomeDir).toHaveBeenCalledWith(); expect(join).toHaveBeenCalledWith(mockHomeDir, ".aws", "config"); diff --git a/packages/shared-ini-file-loader/src/getCredentialsFilepath.spec.ts b/packages/shared-ini-file-loader/src/getCredentialsFilepath.spec.ts index 822a8914861..232cf2a9f19 100644 --- a/packages/shared-ini-file-loader/src/getCredentialsFilepath.spec.ts +++ b/packages/shared-ini-file-loader/src/getCredentialsFilepath.spec.ts @@ -1,10 +1,11 @@ import { join } from "path"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { ENV_CREDENTIALS_PATH, getCredentialsFilepath } from "./getCredentialsFilepath"; import { getHomeDir } from "./getHomeDir"; -jest.mock("path"); -jest.mock("./getHomeDir"); +vi.mock("path"); +vi.mock("./getHomeDir"); describe(getCredentialsFilepath.name, () => { const mockSeparator = "/"; @@ -14,12 +15,12 @@ describe(getCredentialsFilepath.name, () => { const defaultConfigFilepath = `${mockHomeDir}/.aws/credentials`; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns configFilePath from default locations", () => { - (join as jest.Mock).mockImplementation((...args) => args.join(mockSeparator)); - (getHomeDir as jest.Mock).mockReturnValue(mockHomeDir); + vi.mocked(join).mockImplementation((...args) => args.join(mockSeparator)); + vi.mocked(getHomeDir).mockReturnValue(mockHomeDir); expect(getCredentialsFilepath()).toStrictEqual(defaultConfigFilepath); expect(getHomeDir).toHaveBeenCalledWith(); expect(join).toHaveBeenCalledWith(mockHomeDir, ".aws", "credentials"); diff --git a/packages/shared-ini-file-loader/src/getHomeDir.spec.ts b/packages/shared-ini-file-loader/src/getHomeDir.spec.ts index f1d6ccb908b..db10b4c8afc 100644 --- a/packages/shared-ini-file-loader/src/getHomeDir.spec.ts +++ b/packages/shared-ini-file-loader/src/getHomeDir.spec.ts @@ -1,9 +1,10 @@ import { homedir } from "os"; import { sep } from "path"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getHomeDir } from "./getHomeDir"; -jest.mock("os"); +vi.mock("os"); describe(getHomeDir.name, () => { const mockUid = 1; @@ -16,7 +17,7 @@ describe(getHomeDir.name, () => { const OLD_ENV = process.env; beforeEach(() => { - (homedir as jest.Mock).mockReturnValue(mockHomeDir); + vi.mocked(homedir).mockReturnValue(mockHomeDir); process.env = { ...OLD_ENV, HOME: mockHOME, @@ -28,7 +29,8 @@ describe(getHomeDir.name, () => { afterEach(() => { process.env = OLD_ENV; - jest.clearAllMocks(); + vi.clearAllMocks(); + vi.resetModules(); }); it("returns value in process.env.HOME first", () => { @@ -62,35 +64,33 @@ describe(getHomeDir.name, () => { }); it("returns value from homedir fourth", () => { - const processGeteuidSpy = jest.spyOn(process, "geteuid").mockReturnValue(mockUid); + const processGeteuidSpy = vi.spyOn(process, "geteuid").mockReturnValue(mockUid); process.env = { ...process.env, HOME: undefined, USERPROFILE: undefined, HOMEPATH: undefined }; expect(getHomeDir()).toEqual(mockHomeDir); expect(homedir).toHaveBeenCalledTimes(1); expect(processGeteuidSpy).toHaveBeenCalledTimes(1); }); - describe("makes one homedir call irrespective of getHomeDir calls", () => { - const testSingleHomeDirCall = (num: number) => { - jest.isolateModules(() => { - const { getHomeDir } = require("./getHomeDir"); - process.env = { ...process.env, HOME: undefined, USERPROFILE: undefined, HOMEPATH: undefined }; + describe("makes one homedir call irrespective of getHomeDir calls", async () => { + const testSingleHomeDirCall = async (num: number) => { + const { getHomeDir } = await import("./getHomeDir"); + process.env = { ...process.env, HOME: undefined, USERPROFILE: undefined, HOMEPATH: undefined }; - expect(homedir).not.toHaveBeenCalled(); - const homeDirArr = Array(num) - .fill(num) - .map(() => getHomeDir()); - expect(homeDirArr).toStrictEqual(Array(num).fill(mockHomeDir)); + expect(homedir).not.toHaveBeenCalled(); + const homeDirArr = Array(num) + .fill(num) + .map(() => getHomeDir()); + expect(homeDirArr).toStrictEqual(Array(num).fill(mockHomeDir)); - // There is one homedir call even through getHomeDir is called num times. - expect(homedir).toHaveBeenCalledTimes(1); - }); + // There is one homedir call even through getHomeDir is called num times. + expect(homedir).toHaveBeenCalledTimes(1); }; describe("when geteuid is available", () => { - it.each([10, 100, 1000, 10000])("calls: %d ", (num: number) => { - const processGeteuidSpy = jest.spyOn(process, "geteuid").mockReturnValue(mockUid); + it.each([10, 100, 1000, 10000])("calls: %d ", async (num: number) => { + const processGeteuidSpy = vi.spyOn(process, "geteuid").mockReturnValue(mockUid); expect(processGeteuidSpy).not.toHaveBeenCalled(); - testSingleHomeDirCall(num); + await testSingleHomeDirCall(num); expect(processGeteuidSpy).toHaveBeenCalledTimes(num); }); }); @@ -111,35 +111,34 @@ describe(getHomeDir.name, () => { }); }); - describe("makes multiple homedir calls with based on UIDs", () => { - it.each([2, 10, 100])("calls: %d ", (num: number) => { - jest.isolateModules(() => { - const { getHomeDir } = require("./getHomeDir"); - const processGeteuidSpy = jest.spyOn(process, "geteuid").mockReturnValue(mockUid); - for (let i = 0; i < num; i++) { - jest.spyOn(process, "geteuid").mockReturnValueOnce(mockUid + i); - } - process.env = { ...process.env, HOME: undefined, USERPROFILE: undefined, HOMEPATH: undefined }; - - expect(homedir).not.toHaveBeenCalled(); - expect(processGeteuidSpy).not.toHaveBeenCalled(); - const homeDirArr = Array(num) - .fill(num) - .map(() => getHomeDir()); - expect(homeDirArr).toStrictEqual(Array(num).fill(mockHomeDir)); - - // There is num homedir calls as each call returns different UID - expect(homedir).toHaveBeenCalledTimes(num); - expect(processGeteuidSpy).toHaveBeenCalledTimes(num); - - const homeDir = getHomeDir(); - expect(homeDir).toStrictEqual(mockHomeDir); + describe("makes multiple homedir calls with based on UIDs", async () => { + it.each([2, 10, 100])("calls: %d ", async (num: number) => { + const { getHomeDir } = await import("./getHomeDir"); + const processGeteuidSpy = vi.spyOn(process, "geteuid"); + processGeteuidSpy.mockReturnValue(mockUid); + for (let i = 0; i < num; i++) { + processGeteuidSpy.mockReturnValueOnce(mockUid + i); + } + process.env = { ...process.env, HOME: undefined, USERPROFILE: undefined, HOMEPATH: undefined }; - // No extra calls made to homedir, as mockUid is same as the first call. - expect(homedir).toHaveBeenCalledTimes(num); - // Extra call was made to geteuid to get the same UID as the first call. - expect(processGeteuidSpy).toHaveBeenCalledTimes(num + 1); - }); + expect(homedir).not.toHaveBeenCalled(); + expect(processGeteuidSpy).not.toHaveBeenCalled(); + const homeDirArr = Array(num) + .fill(num) + .map(() => getHomeDir()); + expect(homeDirArr).toStrictEqual(Array(num).fill(mockHomeDir)); + + // There is num homedir calls as each call returns different UID + expect(homedir).toHaveBeenCalledTimes(num); + expect(processGeteuidSpy).toHaveBeenCalledTimes(num); + + const homeDir = getHomeDir(); + expect(homeDir).toStrictEqual(mockHomeDir); + + // No extra calls made to homedir, as mockUid is same as the first call. + expect(homedir).toHaveBeenCalledTimes(num); + // Extra call was made to geteuid to get the same UID as the first call. + expect(processGeteuidSpy).toHaveBeenCalledTimes(num + 1); }); }); }); diff --git a/packages/shared-ini-file-loader/src/getProfileName.spec.ts b/packages/shared-ini-file-loader/src/getProfileName.spec.ts index 9780c3519e1..dd21768fa51 100644 --- a/packages/shared-ini-file-loader/src/getProfileName.spec.ts +++ b/packages/shared-ini-file-loader/src/getProfileName.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it } from "vitest"; + import { DEFAULT_PROFILE, ENV_PROFILE, getProfileName } from "./getProfileName"; describe(getProfileName.name, () => { diff --git a/packages/shared-ini-file-loader/src/getSSOTokenFilepath.spec.ts b/packages/shared-ini-file-loader/src/getSSOTokenFilepath.spec.ts index 3edff44fe41..2f35d4573c6 100644 --- a/packages/shared-ini-file-loader/src/getSSOTokenFilepath.spec.ts +++ b/packages/shared-ini-file-loader/src/getSSOTokenFilepath.spec.ts @@ -1,34 +1,35 @@ import { createHash } from "crypto"; import { join } from "path"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getHomeDir } from "./getHomeDir"; import { getSSOTokenFilepath } from "./getSSOTokenFilepath"; -jest.mock("crypto"); -jest.mock("./getHomeDir"); +vi.mock("crypto"); +vi.mock("./getHomeDir"); describe(getSSOTokenFilepath.name, () => { const mockCacheName = "mockCacheName"; - const mockDigest = jest.fn().mockReturnValue(mockCacheName); - const mockUpdate = jest.fn().mockReturnValue({ digest: mockDigest }); + const mockDigest = vi.fn().mockReturnValue(mockCacheName); + const mockUpdate = vi.fn().mockReturnValue({ digest: mockDigest }); const mockHomeDir = "/home/dir"; const mockSsoStartUrl = "mock_sso_start_url"; beforeEach(() => { - (createHash as jest.Mock).mockReturnValue({ update: mockUpdate }); - (getHomeDir as jest.Mock).mockReturnValue(mockHomeDir); + vi.mocked(createHash).mockReturnValue({ update: mockUpdate }); + vi.mocked(getHomeDir).mockReturnValue(mockHomeDir); }); afterEach(() => { expect(createHash).toHaveBeenCalledWith("sha1"); - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("re-throws error", () => { const mockError = new Error("error"); it("when createHash throws error", () => { - (createHash as jest.Mock).mockImplementationOnce(() => { + vi.mocked(createHash).mockImplementationOnce(() => { throw mockError; }); expect(() => getSSOTokenFilepath(mockSsoStartUrl)).toThrow(mockError); @@ -58,7 +59,7 @@ describe(getSSOTokenFilepath.name, () => { }); it("when getHomeDir() throws error", () => { - (getHomeDir as jest.Mock).mockImplementationOnce(() => { + vi.mocked(getHomeDir).mockImplementationOnce(() => { throw mockError; }); expect(() => getSSOTokenFilepath(mockSsoStartUrl)).toThrow(mockError); diff --git a/packages/shared-ini-file-loader/src/getSSOTokenFromFile.spec.ts b/packages/shared-ini-file-loader/src/getSSOTokenFromFile.spec.ts index c6cb3cac0cc..8c5f9f1a50f 100644 --- a/packages/shared-ini-file-loader/src/getSSOTokenFromFile.spec.ts +++ b/packages/shared-ini-file-loader/src/getSSOTokenFromFile.spec.ts @@ -1,11 +1,12 @@ // ToDo: Change to "fs/promises" when supporting nodejs>=14 import { promises } from "fs"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getSSOTokenFilepath } from "./getSSOTokenFilepath"; import { getSSOTokenFromFile } from "./getSSOTokenFromFile"; -jest.mock("fs", () => ({ promises: { readFile: jest.fn() } })); -jest.mock("./getSSOTokenFilepath"); +vi.mock("fs", () => ({ promises: { readFile: vi.fn() } })); +vi.mock("./getSSOTokenFilepath"); describe(getSSOTokenFromFile.name, () => { const mockSsoStartUrl = "mock_sso_start_url"; @@ -17,17 +18,17 @@ describe(getSSOTokenFromFile.name, () => { }; beforeEach(() => { - (getSSOTokenFilepath as jest.Mock).mockReturnValue(mockSsoTokenFilepath); - (promises.readFile as jest.Mock).mockResolvedValue(JSON.stringify(mockToken)); + vi.mocked(getSSOTokenFilepath).mockReturnValue(mockSsoTokenFilepath); + (promises.readFile as any).mockResolvedValue(JSON.stringify(mockToken)); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("re-throws if getting SSO Token filepath fails", async () => { const expectedError = new Error("error"); - (getSSOTokenFilepath as jest.Mock).mockImplementationOnce(() => { + vi.mocked(getSSOTokenFilepath).mockImplementationOnce(() => { throw expectedError; }); @@ -42,7 +43,7 @@ describe(getSSOTokenFromFile.name, () => { it("re-throws if readFile fails", async () => { const expectedError = new Error("error"); - (promises.readFile as jest.Mock).mockRejectedValue(expectedError); + (promises.readFile as any).mockRejectedValue(expectedError); try { await getSSOTokenFromFile(mockSsoStartUrl); @@ -55,7 +56,7 @@ describe(getSSOTokenFromFile.name, () => { it("re-throws if token is not a valid JSON", async () => { const errMsg = "Unexpected token"; - (promises.readFile as jest.Mock).mockReturnValue("invalid JSON"); + (promises.readFile as any).mockReturnValue("invalid JSON"); try { await getSSOTokenFromFile(mockSsoStartUrl); diff --git a/packages/shared-ini-file-loader/src/getSsoSessionData.spec.ts b/packages/shared-ini-file-loader/src/getSsoSessionData.spec.ts index 21815d3bb70..a86e58f81cd 100644 --- a/packages/shared-ini-file-loader/src/getSsoSessionData.spec.ts +++ b/packages/shared-ini-file-loader/src/getSsoSessionData.spec.ts @@ -1,4 +1,5 @@ import { IniSectionType } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { getSsoSessionData } from "./getSsoSessionData"; import { CONFIG_PREFIX_SEPARATOR } from "./loadSharedConfigFiles"; diff --git a/packages/shared-ini-file-loader/src/loadSharedConfigFiles.spec.ts b/packages/shared-ini-file-loader/src/loadSharedConfigFiles.spec.ts index 1ff7e332dc8..20442f16d99 100644 --- a/packages/shared-ini-file-loader/src/loadSharedConfigFiles.spec.ts +++ b/packages/shared-ini-file-loader/src/loadSharedConfigFiles.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getConfigData } from "./getConfigData"; import { getConfigFilepath } from "./getConfigFilepath"; import { getCredentialsFilepath } from "./getCredentialsFilepath"; @@ -6,12 +8,12 @@ import { loadSharedConfigFiles } from "./loadSharedConfigFiles"; import { parseIni } from "./parseIni"; import { slurpFile } from "./slurpFile"; -jest.mock("./getConfigData"); -jest.mock("./getConfigFilepath"); -jest.mock("./getCredentialsFilepath"); -jest.mock("./parseIni"); -jest.mock("./slurpFile"); -jest.mock("./getHomeDir"); +vi.mock("./getConfigData"); +vi.mock("./getConfigFilepath"); +vi.mock("./getCredentialsFilepath"); +vi.mock("./parseIni"); +vi.mock("./slurpFile"); +vi.mock("./getHomeDir"); describe("loadSharedConfigFiles", () => { const mockConfigFilepath = "/mock/file/path/config"; @@ -23,17 +25,17 @@ describe("loadSharedConfigFiles", () => { const mockHomeDir = "/users/alias"; beforeEach(() => { - (getConfigFilepath as jest.Mock).mockReturnValue(mockConfigFilepath); - (getCredentialsFilepath as jest.Mock).mockReturnValue(mockCredsFilepath); - (parseIni as jest.Mock).mockImplementation((args) => args); - (getConfigData as jest.Mock).mockImplementation((args) => args); - (slurpFile as jest.Mock).mockImplementation((path) => Promise.resolve(path)); - (getHomeDir as jest.Mock).mockReturnValue(mockHomeDir); + vi.mocked(getConfigFilepath).mockReturnValue(mockConfigFilepath); + vi.mocked(getCredentialsFilepath).mockReturnValue(mockCredsFilepath); + vi.mocked(parseIni).mockImplementation((args) => args); + vi.mocked(getConfigData).mockImplementation((args) => args); + vi.mocked(slurpFile).mockImplementation((path) => Promise.resolve(path)); + vi.mocked(getHomeDir).mockReturnValue(mockHomeDir); }); afterEach(() => { - jest.clearAllMocks(); - jest.resetModules(); + vi.clearAllMocks(); + vi.resetModules(); }); it("returns configFile and credentialsFile from default locations", async () => { @@ -69,19 +71,19 @@ describe("loadSharedConfigFiles", () => { describe("swallows error and returns empty configuration", () => { it("when readFile throws error", async () => { - (slurpFile as jest.Mock).mockRejectedValue("error"); + vi.mocked(slurpFile).mockRejectedValue("error"); const sharedConfigFiles = await loadSharedConfigFiles(); expect(sharedConfigFiles).toStrictEqual({ configFile: {}, credentialsFile: {} }); }); it("when parseIni throws error", async () => { - (parseIni as jest.Mock).mockRejectedValue("error"); + vi.mocked(parseIni).mockRejectedValue("error"); const sharedConfigFiles = await loadSharedConfigFiles(); expect(sharedConfigFiles).toStrictEqual({ configFile: {}, credentialsFile: {} }); }); it("when normalizeConfigFile throws error", async () => { - (getConfigData as jest.Mock).mockRejectedValue("error"); + vi.mocked(getConfigData).mockRejectedValue("error"); const sharedConfigFiles = await loadSharedConfigFiles(); expect(sharedConfigFiles).toStrictEqual({ configFile: {}, diff --git a/packages/shared-ini-file-loader/src/loadSsoSessionData.spec.ts b/packages/shared-ini-file-loader/src/loadSsoSessionData.spec.ts index ea2f9e549e4..ef3a25f495a 100644 --- a/packages/shared-ini-file-loader/src/loadSsoSessionData.spec.ts +++ b/packages/shared-ini-file-loader/src/loadSsoSessionData.spec.ts @@ -1,27 +1,29 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { getConfigFilepath } from "./getConfigFilepath"; import { getSsoSessionData } from "./getSsoSessionData"; import { loadSsoSessionData } from "./loadSsoSessionData"; import { parseIni } from "./parseIni"; import { slurpFile } from "./slurpFile"; -jest.mock("./getConfigFilepath"); -jest.mock("./getSsoSessionData"); -jest.mock("./parseIni"); -jest.mock("./slurpFile"); +vi.mock("./getConfigFilepath"); +vi.mock("./getSsoSessionData"); +vi.mock("./parseIni"); +vi.mock("./slurpFile"); describe(loadSsoSessionData.name, () => { const mockConfigFilepath = "/mock/file/path/config"; const mockSsoSessionData = { test: { key: "value" } }; beforeEach(() => { - (getConfigFilepath as jest.Mock).mockReturnValue(mockConfigFilepath); - (parseIni as jest.Mock).mockImplementation((args) => args); - (getSsoSessionData as jest.Mock).mockReturnValue(mockSsoSessionData); - (slurpFile as jest.Mock).mockImplementation((path) => Promise.resolve(path)); + vi.mocked(getConfigFilepath).mockReturnValue(mockConfigFilepath); + vi.mocked(parseIni).mockImplementation((args) => args); + vi.mocked(getSsoSessionData).mockReturnValue(mockSsoSessionData); + vi.mocked(slurpFile).mockImplementation((path) => Promise.resolve(path)); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns configFile from default locations", async () => { @@ -40,19 +42,19 @@ describe(loadSsoSessionData.name, () => { describe("swallows error and returns empty configuration", () => { it("when readFile throws error", async () => { - (slurpFile as jest.Mock).mockRejectedValue("error"); + vi.mocked(slurpFile).mockRejectedValue("error"); const ssoSessionData = await loadSsoSessionData(); expect(ssoSessionData).toStrictEqual({}); }); it("when parseIni throws error", async () => { - (parseIni as jest.Mock).mockRejectedValue("error"); + vi.mocked(parseIni).mockRejectedValue("error"); const ssoSessionData = await loadSsoSessionData(); expect(ssoSessionData).toStrictEqual({}); }); it("when normalizeConfigFile throws error", async () => { - (getSsoSessionData as jest.Mock).mockRejectedValue("error"); + vi.mocked(getSsoSessionData).mockRejectedValue("error"); const ssoSessionData = await loadSsoSessionData(); expect(ssoSessionData).toStrictEqual({}); }); diff --git a/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts b/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts index ba7782d2b0d..fd16b3c18ea 100644 --- a/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts +++ b/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { mergeConfigFiles } from "./mergeConfigFiles"; describe(mergeConfigFiles.name, () => { diff --git a/packages/shared-ini-file-loader/src/parseIni.spec.ts b/packages/shared-ini-file-loader/src/parseIni.spec.ts index efa7ecc1ead..c34107b1a03 100644 --- a/packages/shared-ini-file-loader/src/parseIni.spec.ts +++ b/packages/shared-ini-file-loader/src/parseIni.spec.ts @@ -1,4 +1,5 @@ import { IniSectionType } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { CONFIG_PREFIX_SEPARATOR } from "./loadSharedConfigFiles"; import { parseIni } from "./parseIni"; diff --git a/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts b/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts index 9803392d546..b35d3fc6b70 100644 --- a/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts +++ b/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts @@ -1,7 +1,9 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { loadSharedConfigFiles } from "./loadSharedConfigFiles"; import { parseKnownFiles } from "./parseKnownFiles"; -jest.mock("./loadSharedConfigFiles"); +vi.mock("./loadSharedConfigFiles"); describe(parseKnownFiles.name, () => { const mockConfigFile = { @@ -14,11 +16,11 @@ describe(parseKnownFiles.name, () => { }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("gets parsedFiles from loadSharedConfigFiles", async () => { - (loadSharedConfigFiles as jest.Mock).mockReturnValue( + vi.mocked(loadSharedConfigFiles).mockReturnValue( Promise.resolve({ configFile: mockConfigFile, credentialsFile: mockCredentialsFile, diff --git a/packages/shared-ini-file-loader/src/slurpFile.spec.ts b/packages/shared-ini-file-loader/src/slurpFile.spec.ts index a1e5b87f492..b2f45bb231e 100644 --- a/packages/shared-ini-file-loader/src/slurpFile.spec.ts +++ b/packages/shared-ini-file-loader/src/slurpFile.spec.ts @@ -1,121 +1,110 @@ // ToDo: Change to "fs/promises" when supporting nodejs>=14 import { promises } from "fs"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; -jest.mock("fs", () => ({ promises: { readFile: jest.fn() } })); +vi.mock("fs", () => ({ promises: { readFile: vi.fn() } })); describe("slurpFile", () => { const UTF8 = "utf8"; const getMockFileContents = (path: string, options = UTF8) => JSON.stringify({ path, options }); beforeEach(() => { - (promises.readFile as jest.Mock).mockImplementation(async (path, options) => { + (promises.readFile as any).mockImplementation(async (path, options) => { await new Promise((resolve) => setTimeout(resolve, 100)); return getMockFileContents(path, options); }); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); + vi.resetModules(); }); describe("makes one readFile call for a filepath irrespective of slurpFile calls", () => { - // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34617 - it.each([10, 100, 1000, 10000])("parallel calls: %d ", (num: number, done: Function) => { - jest.isolateModules(async () => { - const { slurpFile } = require("./slurpFile"); - const mockPath = "/mock/path"; - const mockPathContent = getMockFileContents(mockPath); - - expect(promises.readFile).not.toHaveBeenCalled(); - const fileContentArr = await Promise.all(Array(num).fill(slurpFile(mockPath))); - expect(fileContentArr).toStrictEqual(Array(num).fill(mockPathContent)); - - // There is one readFile call even through slurpFile is called in parallel num times. - expect(promises.readFile).toHaveBeenCalledTimes(1); - expect(promises.readFile).toHaveBeenCalledWith(mockPath, UTF8); - done(); - }); + it.each([10, 100, 1000, 10000])("parallel calls: %d ", async (num: number) => { + const { slurpFile } = await import("./slurpFile"); + const mockPath = "/mock/path"; + const mockPathContent = getMockFileContents(mockPath); + + expect(promises.readFile).not.toHaveBeenCalled(); + const fileContentArr = await Promise.all(Array(num).fill(slurpFile(mockPath))); + expect(fileContentArr).toStrictEqual(Array(num).fill(mockPathContent)); + + // There is one readFile call even through slurpFile is called in parallel num times. + expect(promises.readFile).toHaveBeenCalledTimes(1); + expect(promises.readFile).toHaveBeenCalledWith(mockPath, UTF8); }); - it("two parallel calls and one sequential call", (done) => { - jest.isolateModules(async () => { - const { slurpFile } = require("./slurpFile"); - const mockPath = "/mock/path"; - const mockPathContent = getMockFileContents(mockPath); + it("two parallel calls and one sequential call", async () => { + const { slurpFile } = await import("./slurpFile"); + const mockPath = "/mock/path"; + const mockPathContent = getMockFileContents(mockPath); - expect(promises.readFile).not.toHaveBeenCalled(); - const fileContentArr = await Promise.all([slurpFile(mockPath), slurpFile(mockPath)]); - expect(fileContentArr).toStrictEqual([mockPathContent, mockPathContent]); + expect(promises.readFile).not.toHaveBeenCalled(); + const fileContentArr = await Promise.all([slurpFile(mockPath), slurpFile(mockPath)]); + expect(fileContentArr).toStrictEqual([mockPathContent, mockPathContent]); - // There is one readFile call even through slurpFile is called in parallel twice. - expect(promises.readFile).toHaveBeenCalledTimes(1); - expect(promises.readFile).toHaveBeenCalledWith(mockPath, UTF8); + // There is one readFile call even through slurpFile is called in parallel twice. + expect(promises.readFile).toHaveBeenCalledTimes(1); + expect(promises.readFile).toHaveBeenCalledWith(mockPath, UTF8); - const fileContent = await slurpFile(mockPath); - expect(fileContent).toStrictEqual(mockPathContent); + const fileContent = await slurpFile(mockPath); + expect(fileContent).toStrictEqual(mockPathContent); - // There is one readFile call even through slurpFile is called for the third time. - expect(promises.readFile).toHaveBeenCalledTimes(1); - done(); - }); + // There is one readFile call even through slurpFile is called for the third time. + expect(promises.readFile).toHaveBeenCalledTimes(1); }); }); - it("makes multiple readFile calls with based on filepaths", (done) => { - jest.isolateModules(async () => { - const { slurpFile } = require("./slurpFile"); + it("makes multiple readFile calls with based on filepaths", async () => { + const { slurpFile } = await import("./slurpFile"); - const mockPath1 = "/mock/path/1"; - const mockPathContent1 = getMockFileContents(mockPath1); + const mockPath1 = "/mock/path/1"; + const mockPathContent1 = getMockFileContents(mockPath1); - const mockPath2 = "/mock/path/2"; - const mockPathContent2 = getMockFileContents(mockPath2); + const mockPath2 = "/mock/path/2"; + const mockPathContent2 = getMockFileContents(mockPath2); - expect(promises.readFile).not.toHaveBeenCalled(); - const fileContentArr = await Promise.all([slurpFile(mockPath1), slurpFile(mockPath2)]); - expect(fileContentArr).toStrictEqual([mockPathContent1, mockPathContent2]); + expect(promises.readFile).not.toHaveBeenCalled(); + const fileContentArr = await Promise.all([slurpFile(mockPath1), slurpFile(mockPath2)]); + expect(fileContentArr).toStrictEqual([mockPathContent1, mockPathContent2]); - // There are two readFile calls as slurpFile is called in parallel with different filepaths. - expect(promises.readFile).toHaveBeenCalledTimes(2); - expect(promises.readFile).toHaveBeenNthCalledWith(1, mockPath1, UTF8); - expect(promises.readFile).toHaveBeenNthCalledWith(2, mockPath2, UTF8); + // There are two readFile calls as slurpFile is called in parallel with different filepaths. + expect(promises.readFile).toHaveBeenCalledTimes(2); + expect(promises.readFile).toHaveBeenNthCalledWith(1, mockPath1, UTF8); + expect(promises.readFile).toHaveBeenNthCalledWith(2, mockPath2, UTF8); - const fileContent1 = await slurpFile(mockPath1); - expect(fileContent1).toStrictEqual(mockPathContent1); - const fileContent2 = await slurpFile(mockPath2); - expect(fileContent2).toStrictEqual(mockPathContent2); + const fileContent1 = await slurpFile(mockPath1); + expect(fileContent1).toStrictEqual(mockPathContent1); + const fileContent2 = await slurpFile(mockPath2); + expect(fileContent2).toStrictEqual(mockPathContent2); - // There is one readFile call even through slurpFile is called for the third time. - expect(promises.readFile).toHaveBeenCalledTimes(2); - done(); - }); + // There is one readFile call even through slurpFile is called for the third time. + expect(promises.readFile).toHaveBeenCalledTimes(2); }); - it("makes multiple readFile calls when called with ignoreCache option", (done) => { - jest.isolateModules(async () => { - const { slurpFile } = require("./slurpFile"); + it("makes multiple readFile calls when called with ignoreCache option", async () => { + const { slurpFile } = await import("./slurpFile"); - const mockPath1 = "/mock/path/1"; - const mockPathContent1 = getMockFileContents(mockPath1); + const mockPath1 = "/mock/path/1"; + const mockPathContent1 = getMockFileContents(mockPath1); - expect(promises.readFile).not.toHaveBeenCalled(); - const fileContentArr = await Promise.all([ - slurpFile(mockPath1, { ignoreCache: true }), - slurpFile(mockPath1, { ignoreCache: true }), - ]); - expect(fileContentArr).toStrictEqual([mockPathContent1, mockPathContent1]); - - // There are two readFile calls as slurpFile is called in parallel with the same filepath. - expect(promises.readFile).toHaveBeenCalledTimes(2); - expect(promises.readFile).toHaveBeenNthCalledWith(1, mockPath1, UTF8); - expect(promises.readFile).toHaveBeenNthCalledWith(2, mockPath1, UTF8); - - const fileContent1 = await slurpFile(mockPath1); - expect(fileContent1).toStrictEqual(mockPathContent1); - - // There is no readFile call since slurpFile is now called without refresh. - expect(promises.readFile).toHaveBeenCalledTimes(2); - done(); - }); + expect(promises.readFile).not.toHaveBeenCalled(); + const fileContentArr = await Promise.all([ + slurpFile(mockPath1, { ignoreCache: true }), + slurpFile(mockPath1, { ignoreCache: true }), + ]); + expect(fileContentArr).toStrictEqual([mockPathContent1, mockPathContent1]); + + // There are two readFile calls as slurpFile is called in parallel with the same filepath. + expect(promises.readFile).toHaveBeenCalledTimes(2); + expect(promises.readFile).toHaveBeenNthCalledWith(1, mockPath1, UTF8); + expect(promises.readFile).toHaveBeenNthCalledWith(2, mockPath1, UTF8); + + const fileContent1 = await slurpFile(mockPath1); + expect(fileContent1).toStrictEqual(mockPathContent1); + + // There is no readFile call since slurpFile is now called without refresh. + expect(promises.readFile).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/shared-ini-file-loader/vitest.config.ts b/packages/shared-ini-file-loader/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/shared-ini-file-loader/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/signature-v4/jest.config.js b/packages/signature-v4/jest.config.js deleted file mode 100644 index 64f3d932819..00000000000 --- a/packages/signature-v4/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - //only test cjs dist, avoid testing the package twice - testPathIgnorePatterns: ["/node_modules/", "/es/"], -}; diff --git a/packages/signature-v4/package.json b/packages/signature-v4/package.json index ccd0952ce7f..8d9ac97237a 100644 --- a/packages/signature-v4/package.json +++ b/packages/signature-v4/package.json @@ -16,7 +16,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest --coverage" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/signature-v4/src/HeaderFormatter.spec.ts b/packages/signature-v4/src/HeaderFormatter.spec.ts index a33746df628..4f6d73aecbf 100644 --- a/packages/signature-v4/src/HeaderFormatter.spec.ts +++ b/packages/signature-v4/src/HeaderFormatter.spec.ts @@ -1,4 +1,5 @@ import type { MessageHeaders } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { HeaderFormatter, Int64 } from "./HeaderFormatter"; diff --git a/packages/signature-v4/src/SignatureV4.spec.ts b/packages/signature-v4/src/SignatureV4.spec.ts index 71c4e54e676..394b5b99e59 100644 --- a/packages/signature-v4/src/SignatureV4.spec.ts +++ b/packages/signature-v4/src/SignatureV4.spec.ts @@ -1,6 +1,7 @@ import { Sha256 } from "@aws-crypto/sha256-js"; import { HttpRequest } from "@smithy/protocol-http"; import { AwsCredentialIdentity, SignableMessage, TimestampHeaderValue } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { ALGORITHM_IDENTIFIER, @@ -837,12 +838,12 @@ describe("SignatureV4", () => { const mockDate = new Date(); beforeEach(() => { - dateSpy = jest.spyOn(global, "Date").mockImplementation(() => mockDate as unknown as string); + dateSpy = vi.spyOn(global, "Date").mockImplementation(() => mockDate as unknown as string); }); afterEach(() => { expect(dateSpy).toHaveBeenCalledTimes(1); - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should use the current date for presigning if no signing date was supplied", async () => { diff --git a/packages/signature-v4/src/credentialDerivation.spec.ts b/packages/signature-v4/src/credentialDerivation.spec.ts index bfeb17c7349..3596f269227 100644 --- a/packages/signature-v4/src/credentialDerivation.spec.ts +++ b/packages/signature-v4/src/credentialDerivation.spec.ts @@ -1,6 +1,7 @@ import { Sha256 } from "@aws-crypto/sha256-js"; import { AwsCredentialIdentity } from "@smithy/types"; import { toHex } from "@smithy/util-hex-encoding"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { clearCredentialCache, createScope, getSigningKey } from "./credentialDerivation"; @@ -34,7 +35,7 @@ describe("getSigningKey", () => { it("should trap errors encountered while hashing", () => { return expect( getSigningKey( - jest.fn(() => { + vi.fn(() => { throw new Error("PANIC"); }), credentials, @@ -47,7 +48,7 @@ describe("getSigningKey", () => { describe("caching", () => { it("should return the same signing key when called with the same date, region, service, and credentials", async () => { - const mockSha256Constructor = jest.fn().mockImplementation((args) => { + const mockSha256Constructor = vi.fn().mockImplementation((args) => { return new Sha256(args); }); const key1 = await getSigningKey(mockSha256Constructor, credentials, shortDate, region, service); diff --git a/packages/signature-v4/src/getCanonicalHeaders.spec.ts b/packages/signature-v4/src/getCanonicalHeaders.spec.ts index b588878be0b..271b6f7fe66 100644 --- a/packages/signature-v4/src/getCanonicalHeaders.spec.ts +++ b/packages/signature-v4/src/getCanonicalHeaders.spec.ts @@ -1,5 +1,6 @@ import { HttpRequest } from "@smithy/protocol-http"; import { HeaderBag } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { ALWAYS_UNSIGNABLE_HEADERS } from "./constants"; import { getCanonicalHeaders } from "./getCanonicalHeaders"; diff --git a/packages/signature-v4/src/getCanonicalQuery.spec.ts b/packages/signature-v4/src/getCanonicalQuery.spec.ts index 15b68a6daca..591763ea4dc 100644 --- a/packages/signature-v4/src/getCanonicalQuery.spec.ts +++ b/packages/signature-v4/src/getCanonicalQuery.spec.ts @@ -1,4 +1,5 @@ import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { getCanonicalQuery } from "./getCanonicalQuery"; diff --git a/packages/signature-v4/src/getPayloadHash.spec.ts b/packages/signature-v4/src/getPayloadHash.spec.ts index ea25a3aa021..a89de781fda 100644 --- a/packages/signature-v4/src/getPayloadHash.spec.ts +++ b/packages/signature-v4/src/getPayloadHash.spec.ts @@ -1,5 +1,6 @@ import { Sha256 } from "@aws-crypto/sha256-js"; import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it, vi } from "vitest"; import { SHA256_HEADER, UNSIGNED_PAYLOAD } from "./constants"; import { getPayloadHash } from "./getPayloadHash"; @@ -28,7 +29,7 @@ describe("getPayloadHash", () => { [SHA256_HEADER]: "foo", }, }), - jest.fn(() => { + vi.fn(() => { throw new Error("I should not have been invoked!"); }) ) diff --git a/packages/signature-v4/src/moveHeadersToQuery.spec.ts b/packages/signature-v4/src/moveHeadersToQuery.spec.ts index 855abd98926..4adc0373099 100644 --- a/packages/signature-v4/src/moveHeadersToQuery.spec.ts +++ b/packages/signature-v4/src/moveHeadersToQuery.spec.ts @@ -1,4 +1,5 @@ import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { moveHeadersToQuery } from "./moveHeadersToQuery"; diff --git a/packages/signature-v4/src/prepareRequest.spec.ts b/packages/signature-v4/src/prepareRequest.spec.ts index 170085a130b..c875822adef 100644 --- a/packages/signature-v4/src/prepareRequest.spec.ts +++ b/packages/signature-v4/src/prepareRequest.spec.ts @@ -1,4 +1,5 @@ import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { AMZ_DATE_HEADER, AUTH_HEADER, DATE_HEADER } from "./constants"; import { prepareRequest } from "./prepareRequest"; diff --git a/packages/signature-v4/src/suite.spec.ts b/packages/signature-v4/src/suite.spec.ts index aed4de8d095..64b852ee255 100644 --- a/packages/signature-v4/src/suite.spec.ts +++ b/packages/signature-v4/src/suite.spec.ts @@ -1,5 +1,6 @@ import { Sha256 } from "@aws-crypto/sha256-js"; import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { SignatureV4 } from "./SignatureV4"; import { credentials, region, requests, service, signingDate } from "./suite.fixture"; diff --git a/packages/signature-v4/src/utilDate.spec.ts b/packages/signature-v4/src/utilDate.spec.ts index 813777874e2..7ce603e4e0e 100644 --- a/packages/signature-v4/src/utilDate.spec.ts +++ b/packages/signature-v4/src/utilDate.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { iso8601, toDate } from "./utilDate"; const toIsoString = "2017-05-22T19:33:14.175Z"; diff --git a/packages/signature-v4/vitest.config.ts b/packages/signature-v4/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/signature-v4/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/smithy-client/jest.config.js b/packages/smithy-client/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/smithy-client/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/smithy-client/package.json b/packages/smithy-client/package.json index b3e474912de..22fcbbd868c 100644 --- a/packages/smithy-client/package.json +++ b/packages/smithy-client/package.json @@ -12,7 +12,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest --passWithNoTests" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/smithy-client/src/client.spec.ts b/packages/smithy-client/src/client.spec.ts index aca906032da..2e9d05c77c0 100644 --- a/packages/smithy-client/src/client.spec.ts +++ b/packages/smithy-client/src/client.spec.ts @@ -1,10 +1,12 @@ +import { beforeEach, describe, expect, test as it, vi } from "vitest"; + import { Client } from "./client"; describe("SmithyClient", () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const mockHandler = jest.fn((args: any) => Promise.resolve({ output: "foo" })); + const mockHandler = vi.fn((args: any) => Promise.resolve({ output: "foo" })); // eslint-disable-next-line @typescript-eslint/no-unused-vars - const mockResolveMiddleware = jest.fn((args) => mockHandler); + const mockResolveMiddleware = vi.fn((args) => mockHandler); // eslint-disable-next-line @typescript-eslint/no-unused-vars const getCommandWithOutput = (output: string) => ({ resolveMiddleware: mockResolveMiddleware, @@ -12,7 +14,7 @@ describe("SmithyClient", () => { const client = new Client({ cacheMiddleware: true } as any); beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should return response promise when only command is supplied", async () => { @@ -30,25 +32,31 @@ describe("SmithyClient", () => { expect(mockResolveMiddleware.mock.calls[0][2 as any]).toEqual(options); }); - it("should apply callback when command and callback is supplied", (done) => { - const callback = jest.fn((err, response) => { + it("should apply callback when command and callback is supplied", async () => { + let resolve: Function; + const promise = new Promise((r) => (resolve = r)); + const callback = vi.fn((err, response) => { expect(response).toEqual("foo"); - done(); + resolve(); }); client.send(getCommandWithOutput("foo") as any, callback); + await promise; }); - it("should apply callback when command, options and callback is supplied", (done) => { - const callback = jest.fn((err, response) => { + it("should apply callback when command, options and callback is supplied", async () => { + let resolve: Function; + const promise = new Promise((r) => (resolve = r)); + const callback = vi.fn((err, response) => { expect(response).toEqual("foo"); expect(mockResolveMiddleware.mock.calls.length).toEqual(1); expect(mockResolveMiddleware.mock.calls[0][2 as any]).toEqual(options); - done(); + resolve(); }); const options = { AbortSignal: "bar", }; client.send(getCommandWithOutput("foo") as any, options, callback); + await promise; }); describe("handler caching", () => { diff --git a/packages/smithy-client/src/command.spec.ts b/packages/smithy-client/src/command.spec.ts index 651a608229a..d2d4434bd2e 100644 --- a/packages/smithy-client/src/command.spec.ts +++ b/packages/smithy-client/src/command.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { Command } from "./command"; describe(Command.name, () => { diff --git a/packages/smithy-client/src/create-aggregated-client.spec.ts b/packages/smithy-client/src/create-aggregated-client.spec.ts index b0ea19c6eae..6de932fd688 100644 --- a/packages/smithy-client/src/create-aggregated-client.spec.ts +++ b/packages/smithy-client/src/create-aggregated-client.spec.ts @@ -1,7 +1,9 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { createAggregatedClient } from "./create-aggregated-client"; class BaseClient { - send = jest.fn() as any; + send = vi.fn() as any; } class AggregatedClient extends BaseClient { constructor(commands) { @@ -14,7 +16,7 @@ class UserClient extends AggregatedClient {} describe(createAggregatedClient.name, () => { it("extends its base client", async () => { const commands = { - ActionCommand: jest.fn(), + ActionCommand: vi.fn(), }; const aggregatedClient: any = new AggregatedClient(commands); @@ -25,7 +27,7 @@ describe(createAggregatedClient.name, () => { it("is extensible", async () => { const commands = { - ActionCommand: jest.fn(), + ActionCommand: vi.fn(), }; const aggregatedClient: any = new UserClient(commands); @@ -37,7 +39,7 @@ describe(createAggregatedClient.name, () => { it("should dispatch using the command lookup", async () => { const commands = { - ActionCommand: jest.fn(), + ActionCommand: vi.fn(), }; const aggregatedClient: any = new AggregatedClient(commands); @@ -49,7 +51,7 @@ describe(createAggregatedClient.name, () => { it("should call send with the matching command", async () => { const commands = { - ActionCommand: jest.fn(), + ActionCommand: vi.fn(), }; const aggregatedClient: any = new AggregatedClient(commands); diff --git a/packages/smithy-client/src/date-utils.spec.ts b/packages/smithy-client/src/date-utils.spec.ts index 519f266e884..7a8e162e79d 100644 --- a/packages/smithy-client/src/date-utils.spec.ts +++ b/packages/smithy-client/src/date-utils.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { parseEpochTimestamp, parseRfc3339DateTime, diff --git a/packages/smithy-client/src/emitWarningIfUnsupportedVersion.spec.ts b/packages/smithy-client/src/emitWarningIfUnsupportedVersion.spec.ts index 6d228d49e24..775726ef765 100644 --- a/packages/smithy-client/src/emitWarningIfUnsupportedVersion.spec.ts +++ b/packages/smithy-client/src/emitWarningIfUnsupportedVersion.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + describe.skip("emitWarningIfUnsupportedVersion", () => { let emitWarningIfUnsupportedVersion; const emitWarning = process.emitWarning; @@ -9,8 +11,8 @@ describe.skip("emitWarningIfUnsupportedVersion", () => { }); afterEach(() => { - jest.clearAllMocks(); - jest.resetModules(); + vi.clearAllMocks(); + vi.resetModules(); process.emitWarning = emitWarning; }); @@ -31,7 +33,7 @@ describe.skip("emitWarningIfUnsupportedVersion", () => { [getPreviousMajorVersion(major), 0, 0], ].map((arr) => `v${arr.join(".")}`) )(`%s`, async (unsupportedVersion) => { - process.emitWarning = jest.fn(); + process.emitWarning = vi.fn(); emitWarningIfUnsupportedVersion(unsupportedVersion); // Verify that the warning was emitted. @@ -54,7 +56,7 @@ describe.skip("emitWarningIfUnsupportedVersion", () => { [major + 1, 0, 0], ].map((arr) => `v${arr.join(".")}`) )(`%s`, async (unsupportedVersion) => { - process.emitWarning = jest.fn(); + process.emitWarning = vi.fn(); emitWarningIfUnsupportedVersion(unsupportedVersion); expect(process.emitWarning).not.toHaveBeenCalled(); }); diff --git a/packages/smithy-client/src/exceptions.spec.ts b/packages/smithy-client/src/exceptions.spec.ts index 89eb66734fd..b82722e0298 100644 --- a/packages/smithy-client/src/exceptions.spec.ts +++ b/packages/smithy-client/src/exceptions.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { decorateServiceException, ExceptionOptionType, ServiceException } from "./exceptions"; it("ServiceException extends from Error", () => { diff --git a/packages/smithy-client/src/get-value-from-text-node.spec.ts b/packages/smithy-client/src/get-value-from-text-node.spec.ts index 49d96dfdca5..4229e31c039 100644 --- a/packages/smithy-client/src/get-value-from-text-node.spec.ts +++ b/packages/smithy-client/src/get-value-from-text-node.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { getValueFromTextNode } from "./get-value-from-text-node"; describe("getValueFromTextNode", () => { diff --git a/packages/smithy-client/src/is-serializable-header-value.spec.ts b/packages/smithy-client/src/is-serializable-header-value.spec.ts index 80370e4ad29..1174a787dd4 100644 --- a/packages/smithy-client/src/is-serializable-header-value.spec.ts +++ b/packages/smithy-client/src/is-serializable-header-value.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isSerializableHeaderValue } from "./is-serializable-header-value"; describe(isSerializableHeaderValue.name, () => { diff --git a/packages/smithy-client/src/lazy-json.spec.ts b/packages/smithy-client/src/lazy-json.spec.ts index 7d1ef59d6ac..835fae1bcb0 100644 --- a/packages/smithy-client/src/lazy-json.spec.ts +++ b/packages/smithy-client/src/lazy-json.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { LazyJsonString } from "./lazy-json"; describe("LazyJsonString", () => { it("should has string methods", () => { diff --git a/packages/smithy-client/src/object-mapping.spec.ts b/packages/smithy-client/src/object-mapping.spec.ts index 3ddede93e0f..f6b6044d401 100644 --- a/packages/smithy-client/src/object-mapping.spec.ts +++ b/packages/smithy-client/src/object-mapping.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { map, ObjectMappingInstructions, SourceMappingInstructions, take } from "./object-mapping"; describe("object mapping", () => { diff --git a/packages/smithy-client/src/parse-utils.spec.ts b/packages/smithy-client/src/parse-utils.spec.ts index 2e9edac1e53..455af97344c 100644 --- a/packages/smithy-client/src/parse-utils.spec.ts +++ b/packages/smithy-client/src/parse-utils.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { expectByte, expectFloat32, @@ -78,9 +80,9 @@ describe("expectBoolean", () => { }); describe("reluctantly", () => { - let consoleMock: jest.SpyInstance; + let consoleMock: any; beforeEach(() => { - consoleMock = jest.spyOn(logger, "warn").mockImplementation(); + consoleMock = vi.spyOn(logger, "warn"); }); afterEach(() => { @@ -117,9 +119,9 @@ describe("expectNumber", () => { }); describe("reluctantly", () => { - let consoleMock: jest.SpyInstance; + let consoleMock: any; beforeEach(() => { - consoleMock = jest.spyOn(logger, "warn").mockImplementation(); + consoleMock = vi.spyOn(logger, "warn"); }); afterEach(() => { @@ -353,9 +355,9 @@ describe("expectString", () => { }); describe("reluctantly", () => { - let consoleMock: jest.SpyInstance; + let consoleMock: any; beforeEach(() => { - consoleMock = jest.spyOn(logger, "warn").mockImplementation(); + consoleMock = vi.spyOn(logger, "warn"); }); afterEach(() => { @@ -397,7 +399,7 @@ describe("expectUnion", () => { }); describe("strictParseDouble", () => { - describe("accepts non-numeric floats as strings", () => { + it("accepts non-numeric floats as strings", () => { expect(strictParseDouble("Infinity")).toEqual(Infinity); expect(strictParseDouble("-Infinity")).toEqual(-Infinity); expect(strictParseDouble("NaN")).toEqual(NaN); @@ -450,12 +452,12 @@ describe("strictParseDouble", () => { }); it.each([null, undefined])("accepts %s", (value) => { - expect(strictParseDouble(value)).toEqual(undefined); + expect(strictParseDouble(value as any)).toEqual(undefined); }); }); describe("strictParseFloat32", () => { - describe("accepts non-numeric floats as strings", () => { + it("accepts non-numeric floats as strings", () => { expect(strictParseFloat32("Infinity")).toEqual(Infinity); expect(strictParseFloat32("-Infinity")).toEqual(-Infinity); expect(strictParseFloat32("NaN")).toEqual(NaN); @@ -514,7 +516,7 @@ describe("strictParseFloat32", () => { }); it.each([null, undefined])("accepts %s", (value) => { - expect(strictParseFloat32(value)).toEqual(undefined); + expect(strictParseFloat32(value as any)).toEqual(undefined); }); }); @@ -559,7 +561,7 @@ describe("limitedParseDouble", () => { }); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(limitedParseDouble(value)).toEqual(undefined); }); }); @@ -611,7 +613,7 @@ describe("limitedParseFloat32", () => { }); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(limitedParseFloat32(value)).toEqual(undefined); }); }); @@ -629,7 +631,7 @@ describe("strictParseLong", () => { expect(strictParseLong("1")).toEqual(1); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(strictParseLong(value)).toEqual(undefined); }); @@ -667,7 +669,7 @@ describe("strictParseInt32", () => { expect(strictParseInt32("1")).toEqual(1); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(strictParseInt32(value)).toEqual(undefined); }); @@ -709,7 +711,7 @@ describe("strictParseShort", () => { expect(strictParseShort("1")).toEqual(1); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(strictParseShort(value)).toEqual(undefined); }); @@ -753,7 +755,7 @@ describe("strictParseByte", () => { expect(strictParseByte("1")).toEqual(1); }); - it.each([null, undefined])("accepts %s", (value) => { + it.each([null, undefined])("accepts %s", (value: any) => { expect(strictParseByte(value)).toEqual(undefined); }); diff --git a/packages/smithy-client/src/quote-header.spec.ts b/packages/smithy-client/src/quote-header.spec.ts index 3609f96c22f..1118422cfb9 100644 --- a/packages/smithy-client/src/quote-header.spec.ts +++ b/packages/smithy-client/src/quote-header.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { quoteHeader } from "./quote-header"; describe(quoteHeader.name, () => { diff --git a/packages/smithy-client/src/ser-utils.spec.ts b/packages/smithy-client/src/ser-utils.spec.ts index 98f6db32a1e..6b064ded65a 100644 --- a/packages/smithy-client/src/ser-utils.spec.ts +++ b/packages/smithy-client/src/ser-utils.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { serializeDateTime, serializeFloat } from "./ser-utils"; describe("serializeFloat", () => { diff --git a/packages/smithy-client/src/serde-json.spec.ts b/packages/smithy-client/src/serde-json.spec.ts index 9655947fa45..a6e40aff1ab 100644 --- a/packages/smithy-client/src/serde-json.spec.ts +++ b/packages/smithy-client/src/serde-json.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { _json } from "./serde-json"; describe(_json.name, () => { diff --git a/packages/smithy-client/src/split-every.spec.ts b/packages/smithy-client/src/split-every.spec.ts index e0beecd39c0..cb7a8afafcd 100644 --- a/packages/smithy-client/src/split-every.spec.ts +++ b/packages/smithy-client/src/split-every.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { splitEvery } from "./split-every"; describe("splitEvery", () => { const m1 = "foo"; diff --git a/packages/smithy-client/src/split-header.spec.ts b/packages/smithy-client/src/split-header.spec.ts index 608abf76a06..0bfa0245ac2 100644 --- a/packages/smithy-client/src/split-header.spec.ts +++ b/packages/smithy-client/src/split-header.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { splitHeader } from "./split-header"; describe(splitHeader.name, () => { diff --git a/packages/smithy-client/vitest.config.ts b/packages/smithy-client/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/smithy-client/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/types/src/http.ts b/packages/types/src/http.ts index 86679b776bf..5abeebcb5cb 100644 --- a/packages/types/src/http.ts +++ b/packages/types/src/http.ts @@ -32,6 +32,7 @@ export interface HttpRequest extends HttpMessage, URI { */ export interface HttpResponse extends HttpMessage { statusCode: number; + reason?: string; } /** diff --git a/packages/url-parser/jest.config.js b/packages/url-parser/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/url-parser/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/url-parser/package.json b/packages/url-parser/package.json index c639d9dbb21..e3b3bcf603f 100644 --- a/packages/url-parser/package.json +++ b/packages/url-parser/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/url-parser/src/index.spec.ts b/packages/url-parser/src/index.spec.ts index 04c0b509b6f..5e1855e883c 100644 --- a/packages/url-parser/src/index.spec.ts +++ b/packages/url-parser/src/index.spec.ts @@ -1,4 +1,5 @@ import { Endpoint } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { parseUrl } from "."; @@ -37,7 +38,7 @@ describe("parseUrl", () => { ], ]); - const testFunc = typeof URL !== "undefined" ? it : xit; + const testFunc = typeof URL !== "undefined" ? it : it.skip; for (const [url, parsed] of testCases) { testFunc(`should correctly parse ${url}`, () => { diff --git a/packages/url-parser/vitest.config.ts b/packages/url-parser/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/url-parser/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-base64/jest.config.js b/packages/util-base64/jest.config.js deleted file mode 100644 index 95d8863b22a..00000000000 --- a/packages/util-base64/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testMatch: ["**/*.spec.ts"], -}; diff --git a/packages/util-base64/package.json b/packages/util-base64/package.json index 0399db824b0..204164225a1 100644 --- a/packages/util-base64/package.json +++ b/packages/util-base64/package.json @@ -14,7 +14,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-base64/src/fromBase64.browser.spec.ts b/packages/util-base64/src/fromBase64.browser.spec.ts index 9209f99d9b0..c1f686772a5 100644 --- a/packages/util-base64/src/fromBase64.browser.spec.ts +++ b/packages/util-base64/src/fromBase64.browser.spec.ts @@ -1,6 +1,5 @@ -/** - * @jest-environment jsdom - */ +import { describe, expect, test as it } from "vitest"; + import testCases from "./__mocks__/testCases.json"; import { fromBase64 } from "./fromBase64.browser"; diff --git a/packages/util-base64/src/fromBase64.spec.ts b/packages/util-base64/src/fromBase64.spec.ts index af3c200efae..d4d663fb4ec 100644 --- a/packages/util-base64/src/fromBase64.spec.ts +++ b/packages/util-base64/src/fromBase64.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import testCases from "./__mocks__/testCases.json"; import { fromBase64 } from "./fromBase64"; diff --git a/packages/util-base64/src/toBase64.browser.spec.ts b/packages/util-base64/src/toBase64.browser.spec.ts index d496ecf3163..3e10bf85992 100644 --- a/packages/util-base64/src/toBase64.browser.spec.ts +++ b/packages/util-base64/src/toBase64.browser.spec.ts @@ -1,7 +1,5 @@ -/** - * @jest-environment jsdom - */ import type { Encoder } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import testCases from "./__mocks__/testCases.json"; import { fromBase64 } from "./fromBase64.browser"; diff --git a/packages/util-base64/src/toBase64.spec.ts b/packages/util-base64/src/toBase64.spec.ts index ae60b4ffdb5..cd99cfbd9f7 100644 --- a/packages/util-base64/src/toBase64.spec.ts +++ b/packages/util-base64/src/toBase64.spec.ts @@ -1,4 +1,5 @@ import type { Encoder } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import testCases from "./__mocks__/testCases.json"; import { toBase64 } from "./toBase64"; diff --git a/packages/util-base64/vitest.config.ts b/packages/util-base64/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-base64/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-body-length-browser/jest.config.js b/packages/util-body-length-browser/jest.config.js deleted file mode 100644 index bd895a5df03..00000000000 --- a/packages/util-body-length-browser/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testEnvironment: "jsdom", -}; diff --git a/packages/util-body-length-browser/package.json b/packages/util-body-length-browser/package.json index c1eaae16cf2..6f906f2dafb 100644 --- a/packages/util-body-length-browser/package.json +++ b/packages/util-body-length-browser/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-body-length-browser/src/calculateBodyLength.spec.ts b/packages/util-body-length-browser/src/calculateBodyLength.spec.ts index 7363894eace..e34cddcf15c 100644 --- a/packages/util-body-length-browser/src/calculateBodyLength.spec.ts +++ b/packages/util-body-length-browser/src/calculateBodyLength.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { calculateBodyLength } from "./calculateBodyLength"; describe(calculateBodyLength.name, () => { diff --git a/packages/util-body-length-browser/vitest.config.ts b/packages/util-body-length-browser/vitest.config.ts new file mode 100644 index 00000000000..73fcc11c317 --- /dev/null +++ b/packages/util-body-length-browser/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/util-body-length-node/jest.config.js b/packages/util-body-length-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-body-length-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-body-length-node/package.json b/packages/util-body-length-node/package.json index 18642f921a4..48641f43b50 100644 --- a/packages/util-body-length-node/package.json +++ b/packages/util-body-length-node/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "devDependencies": { "@types/node": "^16.18.96", diff --git a/packages/util-body-length-node/src/calculateBodyLength.spec.ts b/packages/util-body-length-node/src/calculateBodyLength.spec.ts index 449a08ff663..1be530f21fe 100644 --- a/packages/util-body-length-node/src/calculateBodyLength.spec.ts +++ b/packages/util-body-length-node/src/calculateBodyLength.spec.ts @@ -1,6 +1,7 @@ import * as fs from "fs"; import * as os from "os"; import * as path from "path"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { calculateBodyLength } from "./calculateBodyLength"; @@ -10,7 +11,7 @@ describe(calculateBodyLength.name, () => { const view = new DataView(arrayBuffer); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it.each([ diff --git a/packages/util-body-length-node/vitest.config.ts b/packages/util-body-length-node/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-body-length-node/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-buffer-from/jest.config.js b/packages/util-buffer-from/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-buffer-from/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-buffer-from/package.json b/packages/util-buffer-from/package.json index fa48f8df6b3..36e69856974 100644 --- a/packages/util-buffer-from/package.json +++ b/packages/util-buffer-from/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-buffer-from/src/index.spec.ts b/packages/util-buffer-from/src/index.spec.ts index 8e3728a4573..75c0c3ea9c0 100644 --- a/packages/util-buffer-from/src/index.spec.ts +++ b/packages/util-buffer-from/src/index.spec.ts @@ -1,11 +1,12 @@ import { Buffer } from "buffer"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { fromArrayBuffer, fromString } from "./"; -jest.mock("buffer"); +vi.mock("buffer"); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("fromArrayBuffer", () => { diff --git a/packages/util-buffer-from/vitest.config.ts b/packages/util-buffer-from/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-buffer-from/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-config-provider/jest.config.js b/packages/util-config-provider/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-config-provider/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-config-provider/package.json b/packages/util-config-provider/package.json index 396f10626e3..c4c5f9a8031 100644 --- a/packages/util-config-provider/package.json +++ b/packages/util-config-provider/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest --passWithNoTests" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-config-provider/src/booleanSelector.spec.ts b/packages/util-config-provider/src/booleanSelector.spec.ts index 1632e65de76..14004b30f9d 100644 --- a/packages/util-config-provider/src/booleanSelector.spec.ts +++ b/packages/util-config-provider/src/booleanSelector.spec.ts @@ -1,3 +1,5 @@ +import { beforeEach, describe, expect, test as it } from "vitest"; + import { booleanSelector } from "./booleanSelector"; import { SelectorType } from "./types"; diff --git a/packages/util-config-provider/src/numberSelector.spec.ts b/packages/util-config-provider/src/numberSelector.spec.ts index d18853ecb2c..48a9e8cbe62 100644 --- a/packages/util-config-provider/src/numberSelector.spec.ts +++ b/packages/util-config-provider/src/numberSelector.spec.ts @@ -1,3 +1,5 @@ +import { beforeEach, describe, expect, test as it } from "vitest"; + import { numberSelector } from "./numberSelector"; import { SelectorType } from "./types"; diff --git a/packages/util-config-provider/vitest.config.ts b/packages/util-config-provider/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-config-provider/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-defaults-mode-browser/jest.config.js b/packages/util-defaults-mode-browser/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-defaults-mode-browser/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-defaults-mode-browser/package.json b/packages/util-defaults-mode-browser/package.json index d0b0bec2e30..0efee97e03c 100644 --- a/packages/util-defaults-mode-browser/package.json +++ b/packages/util-defaults-mode-browser/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.native.spec.ts b/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.native.spec.ts index 80c0b1f1cf3..412f06976ce 100644 --- a/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.native.spec.ts +++ b/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.native.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { DEFAULTS_MODE_OPTIONS } from "./constants"; import { resolveDefaultsModeConfig } from "./resolveDefaultsModeConfig.native"; diff --git a/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.spec.ts b/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.spec.ts index 779f5dfcdb5..520bd6616f1 100644 --- a/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.spec.ts +++ b/packages/util-defaults-mode-browser/src/resolveDefaultsModeConfig.spec.ts @@ -1,14 +1,12 @@ -/** - * @jest-environment jsdom - */ import bowser from "bowser"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { DEFAULTS_MODE_OPTIONS } from "./constants"; import { resolveDefaultsModeConfig } from "./resolveDefaultsModeConfig"; -jest.mock("bowser"); +vi.mock("bowser"); describe("resolveDefaultsModeConfig", () => { - const uaSpy = jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue("some UA"); + const uaSpy = vi.spyOn(window.navigator, "userAgent", "get").mockReturnValue("some UA"); afterEach(() => { uaSpy.mockClear(); @@ -24,17 +22,17 @@ describe("resolveDefaultsModeConfig", () => { }); it("should resolve auto mode to mobile if platform is mobile", async () => { - (bowser.parse as jest.Mock).mockReturnValue({ platform: { type: "mobile" } }); + (bowser.parse as any).mockReturnValue({ platform: { type: "mobile" } }); expect(await resolveDefaultsModeConfig({ defaultsMode: () => Promise.resolve("auto") })()).toBe("mobile"); }); it("should resolve auto mode to mobile if platform is tablet", async () => { - (bowser.parse as jest.Mock).mockReturnValue({ platform: { type: "tablet" } }); + (bowser.parse as any).mockReturnValue({ platform: { type: "tablet" } }); expect(await resolveDefaultsModeConfig({ defaultsMode: () => Promise.resolve("auto") })()).toBe("mobile"); }); it("should resolve auto mode to standard if platform not mobile or tablet", async () => { - (bowser.parse as jest.Mock).mockReturnValue({ platform: { type: "desktop" } }); + (bowser.parse as any).mockReturnValue({ platform: { type: "desktop" } }); expect(await resolveDefaultsModeConfig({ defaultsMode: () => Promise.resolve("auto") })()).toBe("standard"); }); diff --git a/packages/util-defaults-mode-browser/vitest.config.ts b/packages/util-defaults-mode-browser/vitest.config.ts new file mode 100644 index 00000000000..73fcc11c317 --- /dev/null +++ b/packages/util-defaults-mode-browser/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/util-defaults-mode-node/jest.config.js b/packages/util-defaults-mode-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-defaults-mode-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-defaults-mode-node/package.json b/packages/util-defaults-mode-node/package.json index 57a795af12a..f26b3ba9e3e 100644 --- a/packages/util-defaults-mode-node/package.json +++ b/packages/util-defaults-mode-node/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-defaults-mode-node/src/resolveDefaultsModeConfig.spec.ts b/packages/util-defaults-mode-node/src/resolveDefaultsModeConfig.spec.ts index d0570c6bafe..f02abc901a7 100644 --- a/packages/util-defaults-mode-node/src/resolveDefaultsModeConfig.spec.ts +++ b/packages/util-defaults-mode-node/src/resolveDefaultsModeConfig.spec.ts @@ -1,6 +1,7 @@ import { NODE_REGION_CONFIG_OPTIONS } from "@smithy/config-resolver"; import * as ImdsProvider from "@smithy/credential-provider-imds"; import * as NodeConfigProvider from "@smithy/node-config-provider"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { AWS_DEFAULT_REGION_ENV, @@ -13,12 +14,12 @@ import { import { NODE_DEFAULTS_MODE_CONFIG_OPTIONS } from "./defaultsModeConfig"; import { resolveDefaultsModeConfig } from "./resolveDefaultsModeConfig"; -jest.mock("@smithy/node-config-provider"); -jest.mock("@smithy/credential-provider-imds"); +vi.mock("@smithy/node-config-provider"); +vi.mock("@smithy/credential-provider-imds"); describe("resolveDefaultsModeConfig", () => { afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should default to legacy", async () => { @@ -40,7 +41,7 @@ describe("resolveDefaultsModeConfig", () => { }); it("should memoize the response", async () => { - const providerMock = jest.fn().mockResolvedValue("legacy"); + const providerMock = vi.fn().mockResolvedValue("legacy"); const defaultsMode = resolveDefaultsModeConfig({ defaultsMode: providerMock }); await defaultsMode(); const mockInvokeCount = providerMock.mock.calls.length; @@ -49,14 +50,14 @@ describe("resolveDefaultsModeConfig", () => { }); it("should resolve client region from Node config provider chain", async () => { - const loadConfigMock = NodeConfigProvider.loadConfig as jest.Mock; + const loadConfigMock = NodeConfigProvider.loadConfig as any; loadConfigMock.mockReturnValueOnce(undefined); expect(await resolveDefaultsModeConfig({ defaultsMode: () => Promise.resolve("mobile") })()).toBe("mobile"); expect(loadConfigMock.mock.calls[0][0]).toBe(NODE_REGION_CONFIG_OPTIONS); }); it("should resolve defaults mode from Node config provider chain", async () => { - const loadConfigMock = NodeConfigProvider.loadConfig as jest.Mock; + const loadConfigMock = NodeConfigProvider.loadConfig as any; loadConfigMock.mockReturnValueOnce("us-west-2").mockReturnValueOnce("mobile"); expect(await resolveDefaultsModeConfig({})()).toBe("mobile"); expect(loadConfigMock.mock.calls[1][0]).toBe(NODE_DEFAULTS_MODE_CONFIG_OPTIONS); @@ -90,10 +91,8 @@ describe("resolveDefaultsModeConfig", () => { it("should make request to IMDS endpoint to resolve client region", async () => { const fakeImdsEndpoint = { path: "foo", hostname: "bar" }; - const getImdsEndpointMock = (ImdsProvider.getInstanceMetadataEndpoint as jest.Mock).mockResolvedValue( - fakeImdsEndpoint - ); - const httpRequestMock = (ImdsProvider.httpRequest as jest.Mock).mockResolvedValue("us-west-2"); + const getImdsEndpointMock = (ImdsProvider.getInstanceMetadataEndpoint as any).mockResolvedValue(fakeImdsEndpoint); + const httpRequestMock = (ImdsProvider.httpRequest as any).mockResolvedValue("us-west-2"); expect(await resolveDefaultsModeConfig({ region: "us-west-1", defaultsMode: "auto" })()).toBe("cross-region"); expect(getImdsEndpointMock).toBeCalled(); expect(httpRequestMock.mock.calls[0][0]).toMatchObject({ ...fakeImdsEndpoint, path: IMDS_REGION_PATH }); @@ -103,8 +102,8 @@ describe("resolveDefaultsModeConfig", () => { it(`should skip calling IMDS if ${ENV_IMDS_DISABLED} is set`, async () => { process.env[ENV_IMDS_DISABLED] = "true"; - const getImdsEndpointMock = ImdsProvider.getInstanceMetadataEndpoint as jest.Mock; - const httpRequestMock = ImdsProvider.httpRequest as jest.Mock; + const getImdsEndpointMock = ImdsProvider.getInstanceMetadataEndpoint as any; + const httpRequestMock = ImdsProvider.httpRequest as any; expect(await resolveDefaultsModeConfig({ region: "us-west-1", defaultsMode: "auto" })()).toBe("standard"); expect(getImdsEndpointMock).not.toBeCalled(); expect(httpRequestMock).not.toBeCalled(); diff --git a/packages/util-defaults-mode-node/vitest.config.ts b/packages/util-defaults-mode-node/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-defaults-mode-node/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-endpoints/jest.config.integ.js b/packages/util-endpoints/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/util-endpoints/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/util-endpoints/jest.config.js b/packages/util-endpoints/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-endpoints/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-endpoints/package.json b/packages/util-endpoints/package.json index 205452c41b2..29f17453ce2 100644 --- a/packages/util-endpoints/package.json +++ b/packages/util-endpoints/package.json @@ -14,8 +14,10 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test": "yarn g:vitest run", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "keywords": [ "endpoint" diff --git a/packages/util-endpoints/src/cache/EndpointCache.spec.ts b/packages/util-endpoints/src/cache/EndpointCache.spec.ts index 589702a1506..1f2f645a37a 100644 --- a/packages/util-endpoints/src/cache/EndpointCache.spec.ts +++ b/packages/util-endpoints/src/cache/EndpointCache.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { EndpointCache } from "./EndpointCache"; describe(EndpointCache.name, () => { diff --git a/packages/util-endpoints/src/getEndpointUrlConfig.spec.ts b/packages/util-endpoints/src/getEndpointUrlConfig.spec.ts index 14555165088..4b819c3d014 100644 --- a/packages/util-endpoints/src/getEndpointUrlConfig.spec.ts +++ b/packages/util-endpoints/src/getEndpointUrlConfig.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it } from "vitest"; + import { getEndpointUrlConfig } from "./getEndpointUrlConfig"; const ENV_ENDPOINT_URL = "AWS_ENDPOINT_URL"; diff --git a/packages/util-endpoints/src/lib/booleanEquals.spec.ts b/packages/util-endpoints/src/lib/booleanEquals.spec.ts index 10a93d8c0dd..aef4f7d3728 100644 --- a/packages/util-endpoints/src/lib/booleanEquals.spec.ts +++ b/packages/util-endpoints/src/lib/booleanEquals.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { booleanEquals } from "./booleanEquals"; describe(booleanEquals.name, () => { diff --git a/packages/util-endpoints/src/lib/getAttr.spec.ts b/packages/util-endpoints/src/lib/getAttr.spec.ts index 56bcf9abfc9..00dedf865fa 100644 --- a/packages/util-endpoints/src/lib/getAttr.spec.ts +++ b/packages/util-endpoints/src/lib/getAttr.spec.ts @@ -1,18 +1,20 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { EndpointError } from "../types"; import { getAttr } from "./getAttr"; import { getAttrPathList } from "./getAttrPathList"; -jest.mock("./getAttrPathList"); +vi.mock("./getAttrPathList"); describe(getAttr.name, () => { const testSuccess = (value: any, input: string, output: unknown, pathList: string[]) => { - (getAttrPathList as jest.Mock).mockReturnValueOnce(pathList); + vi.mocked(getAttrPathList).mockReturnValueOnce(pathList); expect(getAttr(value, input)).toEqual(output); expect(getAttrPathList).toHaveBeenCalledWith(input); }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("object", () => { @@ -42,7 +44,7 @@ describe(getAttr.name, () => { it("rethrows error from getAttrPathList", () => { const mockPath = "mockPath"; const mockError = new Error("test"); - (getAttrPathList as jest.Mock).mockImplementationOnce(() => { + vi.mocked(getAttrPathList).mockImplementationOnce(() => { throw mockError; }); expect(() => getAttr({}, mockPath)).toThrow(mockError); @@ -52,7 +54,7 @@ describe(getAttr.name, () => { it("throws error if attribute parent is not defined", () => { const mockPath = "foo.bar"; const mockObj = { foo: "bar" }; - (getAttrPathList as jest.Mock).mockReturnValueOnce(mockPath.split(".")); + vi.mocked(getAttrPathList).mockReturnValueOnce(mockPath.split(".")); expect(() => getAttr(mockObj, mockPath)).toThrow( new EndpointError(`Index 'bar' in '${mockPath}' not found in '${JSON.stringify(mockObj)}'`) ); diff --git a/packages/util-endpoints/src/lib/getAttrPathList.spec.ts b/packages/util-endpoints/src/lib/getAttrPathList.spec.ts index 4e6a03b4ebb..e5504a60c5f 100644 --- a/packages/util-endpoints/src/lib/getAttrPathList.spec.ts +++ b/packages/util-endpoints/src/lib/getAttrPathList.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { EndpointError } from "../types"; import { getAttrPathList } from "./getAttrPathList"; diff --git a/packages/util-endpoints/src/lib/isIpAddress.spec.ts b/packages/util-endpoints/src/lib/isIpAddress.spec.ts index b8fb77ef07c..20d4297ee42 100644 --- a/packages/util-endpoints/src/lib/isIpAddress.spec.ts +++ b/packages/util-endpoints/src/lib/isIpAddress.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isIpAddress } from "./isIpAddress"; describe(isIpAddress.name, () => { diff --git a/packages/util-endpoints/src/lib/isSet.spec.ts b/packages/util-endpoints/src/lib/isSet.spec.ts index cc01b384097..49a4f710146 100644 --- a/packages/util-endpoints/src/lib/isSet.spec.ts +++ b/packages/util-endpoints/src/lib/isSet.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isSet } from "./isSet"; describe(isSet.name, () => { diff --git a/packages/util-endpoints/src/lib/isValidHostLabel.spec.ts b/packages/util-endpoints/src/lib/isValidHostLabel.spec.ts index 9a23d78a3bd..2a0663e3bcf 100644 --- a/packages/util-endpoints/src/lib/isValidHostLabel.spec.ts +++ b/packages/util-endpoints/src/lib/isValidHostLabel.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { isValidHostLabel } from "./isValidHostLabel"; describe(isValidHostLabel.name, () => { diff --git a/packages/util-endpoints/src/lib/not.spec.ts b/packages/util-endpoints/src/lib/not.spec.ts index ae52309ec51..6e2c8ae6fa7 100644 --- a/packages/util-endpoints/src/lib/not.spec.ts +++ b/packages/util-endpoints/src/lib/not.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { not } from "./not"; describe(not.name, () => { diff --git a/packages/util-endpoints/src/lib/parseURL.spec.ts b/packages/util-endpoints/src/lib/parseURL.spec.ts index 4e8b6d1f516..0943a35c23e 100644 --- a/packages/util-endpoints/src/lib/parseURL.spec.ts +++ b/packages/util-endpoints/src/lib/parseURL.spec.ts @@ -1,4 +1,5 @@ import { Endpoint, EndpointURL, EndpointURLScheme } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { parseURL } from "./parseURL"; diff --git a/packages/util-endpoints/src/lib/stringEquals.spec.ts b/packages/util-endpoints/src/lib/stringEquals.spec.ts index aef010a4766..187ba00a479 100644 --- a/packages/util-endpoints/src/lib/stringEquals.spec.ts +++ b/packages/util-endpoints/src/lib/stringEquals.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { stringEquals } from "./stringEquals"; describe(stringEquals.name, () => { diff --git a/packages/util-endpoints/src/lib/substring.spec.ts b/packages/util-endpoints/src/lib/substring.spec.ts index 9246fef8685..a2e845da8a6 100644 --- a/packages/util-endpoints/src/lib/substring.spec.ts +++ b/packages/util-endpoints/src/lib/substring.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { substring } from "./substring"; describe(substring.name, () => { diff --git a/packages/util-endpoints/src/lib/uriEncode.spec.ts b/packages/util-endpoints/src/lib/uriEncode.spec.ts index 0158cef63bc..19b468dfa49 100644 --- a/packages/util-endpoints/src/lib/uriEncode.spec.ts +++ b/packages/util-endpoints/src/lib/uriEncode.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { uriEncode } from "./uriEncode"; describe(uriEncode.name, () => { diff --git a/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts b/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts index 133d973f6c1..2b39d207752 100644 --- a/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts +++ b/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts @@ -1,5 +1,6 @@ import { existsSync, readdirSync } from "fs"; import { resolve } from "path"; +import { describe, expect, test as it } from "vitest"; import { resolveEndpoint } from "./resolveEndpoint"; import { EndpointError } from "./types"; @@ -23,7 +24,7 @@ describe(resolveEndpoint.name, () => { for (const testCase of testCases) { const { documentation, params } = testCase; - (testCase.skip ? xit : it)(documentation, () => { + (testCase.skip ? it.skip : it)(documentation, () => { const _expect = testCase.expect; const { endpoint, error } = _expect; diff --git a/packages/util-endpoints/src/resolveEndpoint.spec.ts b/packages/util-endpoints/src/resolveEndpoint.spec.ts index 6f17139d478..6485ae23908 100644 --- a/packages/util-endpoints/src/resolveEndpoint.spec.ts +++ b/packages/util-endpoints/src/resolveEndpoint.spec.ts @@ -1,9 +1,11 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + /* eslint-disable @typescript-eslint/no-unused-vars */ import { resolveEndpoint } from "./resolveEndpoint"; import { EndpointError, EndpointParams, ParameterObject, RuleSetObject } from "./types"; import { evaluateRules } from "./utils"; -jest.mock("./utils"); +vi.mock("./utils"); describe(resolveEndpoint.name, () => { const boolParamKey = "boolParamKey"; @@ -46,11 +48,11 @@ describe(resolveEndpoint.name, () => { const mockResolvedEndpoint = { url: new URL("http://example.com") }; beforeEach(() => { - (evaluateRules as jest.Mock).mockReturnValue(mockResolvedEndpoint); + vi.mocked(evaluateRules).mockReturnValue(mockResolvedEndpoint); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("should use the default value if a parameter is not set", () => { @@ -116,10 +118,10 @@ describe(resolveEndpoint.name, () => { it("should debug proper infos", () => { const { paramWithDefaultKey: ignored, ...endpointParamsWithoutDefault } = mockEndpointParams; const mockLogger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }; const resolvedEndpoint = resolveEndpoint(mockRuleSetObject, { diff --git a/packages/util-endpoints/src/utils/callFunction.spec.ts b/packages/util-endpoints/src/utils/callFunction.spec.ts index 2bd03a8e1b4..105d334f568 100644 --- a/packages/util-endpoints/src/utils/callFunction.spec.ts +++ b/packages/util-endpoints/src/utils/callFunction.spec.ts @@ -1,9 +1,11 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { callFunction } from "./callFunction"; import { customEndpointFunctions } from "./customEndpointFunctions"; import { endpointFunctions } from "./endpointFunctions"; import { evaluateExpression } from "./evaluateExpression"; -jest.mock("./evaluateExpression"); +vi.mock("./evaluateExpression"); describe(callFunction.name, () => { const mockOptions = { @@ -14,11 +16,11 @@ describe(callFunction.name, () => { const mockArgReturn = "mockArgReturn"; beforeEach(() => { - (evaluateExpression as jest.Mock).mockReturnValue(mockArgReturn); + vi.mocked(evaluateExpression).mockReturnValue(mockArgReturn); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it.each([ @@ -32,7 +34,7 @@ describe(callFunction.name, () => { "subsgtring", "urlEncode", ])("calls built-in endpoint function %s", (builtIn) => { - endpointFunctions[builtIn] = jest.fn().mockReturnValue(mockReturn); + endpointFunctions[builtIn] = vi.fn().mockReturnValue(mockReturn); const mockArg = "mockArg"; const mockFn = { fn: builtIn, argv: [mockArg] }; @@ -67,7 +69,7 @@ describe(callFunction.name, () => { ); it("calls custom endpoint functions", () => { - const mockCustomFunction = jest.fn().mockReturnValue(mockReturn); + const mockCustomFunction = vi.fn().mockReturnValue(mockReturn); customEndpointFunctions["ns"] = { mockCustomFunction, }; diff --git a/packages/util-endpoints/src/utils/evaluateCondition.spec.ts b/packages/util-endpoints/src/utils/evaluateCondition.spec.ts index 6d6c0ebe9af..2f04b37dc74 100644 --- a/packages/util-endpoints/src/utils/evaluateCondition.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateCondition.spec.ts @@ -1,9 +1,11 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { debugId, toDebugString } from "../debug"; import { EndpointError, EvaluateOptions } from "../types"; import { callFunction } from "./callFunction"; import { evaluateCondition } from "./evaluateCondition"; -jest.mock("./callFunction"); +vi.mock("./callFunction"); describe(evaluateCondition.name, () => { const mockOptions: EvaluateOptions = { @@ -33,12 +35,12 @@ describe(evaluateCondition.name, () => { ])("returns %s for", (result, testCases) => { it.each(testCases)(`value: '%s'`, (mockReturn) => { const mockLogger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }; - (callFunction as jest.Mock).mockReturnValue(mockReturn); + vi.mocked(callFunction).mockReturnValue(mockReturn); const { result, toAssign } = evaluateCondition(mockFnArgs, { ...mockOptions, logger: mockLogger }); expect(result).toBe(result); expect(toAssign).toBeUndefined(); @@ -53,12 +55,12 @@ describe(evaluateCondition.name, () => { it("returns assigned value if defined", () => { const mockAssignedValue = "mockAssignedValue"; const mockLogger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }; - (callFunction as jest.Mock).mockReturnValue(mockAssignedValue); + vi.mocked(callFunction).mockReturnValue(mockAssignedValue); const { result, toAssign } = evaluateCondition( { assign: mockAssign, ...mockFnArgs }, { ...mockOptions, logger: mockLogger } diff --git a/packages/util-endpoints/src/utils/evaluateConditions.spec.ts b/packages/util-endpoints/src/utils/evaluateConditions.spec.ts index 154af48495d..161aacd2752 100644 --- a/packages/util-endpoints/src/utils/evaluateConditions.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateConditions.spec.ts @@ -1,16 +1,18 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { debugId, toDebugString } from "../debug"; import { ConditionObject, EvaluateOptions } from "../types"; import { evaluateCondition } from "./evaluateCondition"; import { evaluateConditions } from "./evaluateConditions"; -jest.mock("./evaluateCondition"); +vi.mock("./evaluateCondition"); describe(evaluateConditions.name, () => { const mockLogger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }; const mockOptions: EvaluateOptions = { endpointParams: {}, @@ -21,12 +23,12 @@ describe(evaluateConditions.name, () => { const mockCn2: ConditionObject = { fn: "fn2", argv: ["arg2"], assign: "assign2" }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("returns false as soon as one condition is false", () => { it("first condition is false", () => { - (evaluateCondition as jest.Mock).mockReturnValueOnce({ result: false }); + vi.mocked(evaluateCondition).mockReturnValueOnce({ result: false }); const { result, referenceRecord } = evaluateConditions([mockCn1, mockCn2], mockOptions); expect(result).toBe(false); expect(referenceRecord).toBeUndefined(); @@ -34,8 +36,8 @@ describe(evaluateConditions.name, () => { }); it("second condition is false", () => { - (evaluateCondition as jest.Mock).mockReturnValueOnce({ result: true }); - (evaluateCondition as jest.Mock).mockReturnValueOnce({ result: false }); + vi.mocked(evaluateCondition).mockReturnValueOnce({ result: true }); + vi.mocked(evaluateCondition).mockReturnValueOnce({ result: false }); const { result, referenceRecord } = evaluateConditions([mockCn1, mockCn2], mockOptions); expect(result).toBe(false); expect(referenceRecord).toBeUndefined(); @@ -48,11 +50,11 @@ describe(evaluateConditions.name, () => { const value1 = "value1"; const value2 = "value2"; - (evaluateCondition as jest.Mock).mockReturnValueOnce({ + vi.mocked(evaluateCondition).mockReturnValueOnce({ result: true, toAssign: { name: mockCn1.assign, value: value1 }, }); - (evaluateCondition as jest.Mock).mockReturnValueOnce({ + vi.mocked(evaluateCondition).mockReturnValueOnce({ result: true, toAssign: { name: mockCn2.assign, value: value2 }, }); diff --git a/packages/util-endpoints/src/utils/evaluateEndpointRule.spec.ts b/packages/util-endpoints/src/utils/evaluateEndpointRule.spec.ts index 3fa011831a9..c53427024e5 100644 --- a/packages/util-endpoints/src/utils/evaluateEndpointRule.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateEndpointRule.spec.ts @@ -1,4 +1,5 @@ import { EvaluateOptions } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { debugId, toDebugString } from "../debug"; import { ConditionObject, EndpointRuleObject } from "../types"; @@ -8,17 +9,17 @@ import { getEndpointHeaders } from "./getEndpointHeaders"; import { getEndpointProperties } from "./getEndpointProperties"; import { getEndpointUrl } from "./getEndpointUrl"; -jest.mock("./evaluateConditions"); -jest.mock("./getEndpointUrl"); -jest.mock("./getEndpointHeaders"); -jest.mock("./getEndpointProperties"); +vi.mock("./evaluateConditions"); +vi.mock("./getEndpointUrl"); +vi.mock("./getEndpointHeaders"); +vi.mock("./getEndpointProperties"); describe(evaluateEndpointRule.name, () => { const mockLogger = { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), }; const mockOptions: EvaluateOptions = { endpointParams: {}, @@ -37,7 +38,7 @@ describe(evaluateEndpointRule.name, () => { }; it("returns undefined if conditions are false", () => { - (evaluateConditions as jest.Mock).mockReturnValue({ result: false }); + vi.mocked(evaluateConditions).mockReturnValue({ result: false }); const result = evaluateEndpointRule(mockEndpointRule, mockOptions); expect(result).toBeUndefined(); expect(evaluateConditions).toHaveBeenCalledWith(mockConditions, mockOptions); @@ -55,17 +56,17 @@ describe(evaluateEndpointRule.name, () => { }; beforeEach(() => { - (evaluateConditions as jest.Mock).mockReturnValue({ + vi.mocked(evaluateConditions).mockReturnValue({ result: true, referenceRecord: mockReferenceRecord, }); - (getEndpointUrl as jest.Mock).mockReturnValue(mockEndpointUrl); + vi.mocked(getEndpointUrl).mockReturnValue(mockEndpointUrl); }); afterEach(() => { expect(evaluateConditions).toHaveBeenCalledWith(mockConditions, mockOptions); expect(getEndpointUrl).toHaveBeenCalledWith(mockEndpoint.url, mockUpdatedOptions); - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("without headers and properties", () => { @@ -88,8 +89,8 @@ describe(evaluateEndpointRule.name, () => { const mockOutputHeaders = { headerKey: ["headerOutputValue"] }; const mockOutputProperties = { propertyKey: "propertyOutputValue" }; - (getEndpointHeaders as jest.Mock).mockReturnValue(mockOutputHeaders); - (getEndpointProperties as jest.Mock).mockReturnValue(mockOutputProperties); + vi.mocked(getEndpointHeaders).mockReturnValue(mockOutputHeaders); + vi.mocked(getEndpointProperties).mockReturnValue(mockOutputProperties); const headerEndpoint = { ...mockEndpoint, headers: mockInputHeaders, diff --git a/packages/util-endpoints/src/utils/evaluateErrorRule.spec.ts b/packages/util-endpoints/src/utils/evaluateErrorRule.spec.ts index ca606da2962..422fd679a83 100644 --- a/packages/util-endpoints/src/utils/evaluateErrorRule.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateErrorRule.spec.ts @@ -1,10 +1,12 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { EndpointError, ErrorRuleObject } from "../types"; import { evaluateConditions } from "./evaluateConditions"; import { evaluateErrorRule } from "./evaluateErrorRule"; import { evaluateExpression } from "./evaluateExpression"; -jest.mock("./evaluateConditions"); -jest.mock("./evaluateExpression"); +vi.mock("./evaluateConditions"); +vi.mock("./evaluateExpression"); describe(evaluateErrorRule.name, () => { const mockOptions = { @@ -23,7 +25,7 @@ describe(evaluateErrorRule.name, () => { }; it("returns undefined if conditions evaluate to false", () => { - (evaluateConditions as jest.Mock).mockReturnValue({ result: false }); + vi.mocked(evaluateConditions).mockReturnValue({ result: false }); const result = evaluateErrorRule(mockErrorRule, mockOptions); expect(result).toBeUndefined(); expect(evaluateConditions).toHaveBeenCalledWith(mockConditions, mockOptions); @@ -34,8 +36,8 @@ describe(evaluateErrorRule.name, () => { const mockErrorMsg = "mockErrorMsg"; const mockReferenceRecord = { key: "value" }; - (evaluateConditions as jest.Mock).mockReturnValue({ result: true, referenceRecord: mockReferenceRecord }); - (evaluateExpression as jest.Mock).mockReturnValue(mockErrorMsg); + vi.mocked(evaluateConditions).mockReturnValue({ result: true, referenceRecord: mockReferenceRecord }); + vi.mocked(evaluateExpression).mockReturnValue(mockErrorMsg); expect(() => evaluateErrorRule(mockErrorRule, mockOptions)).toThrowError(new EndpointError(`mockErrorMsg`)); expect(evaluateConditions).toHaveBeenCalledWith(mockConditions, mockOptions); diff --git a/packages/util-endpoints/src/utils/evaluateExpression.spec.ts b/packages/util-endpoints/src/utils/evaluateExpression.spec.ts index 28dfdf64b5d..81c136bf830 100644 --- a/packages/util-endpoints/src/utils/evaluateExpression.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateExpression.spec.ts @@ -1,12 +1,14 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { EndpointError } from "../types"; import { callFunction } from "./callFunction"; import { evaluateExpression } from "./evaluateExpression"; import { evaluateTemplate } from "./evaluateTemplate"; import { getReferenceValue } from "./getReferenceValue"; -jest.mock("./callFunction"); -jest.mock("./getReferenceValue"); -jest.mock("./evaluateTemplate"); +vi.mock("./callFunction"); +vi.mock("./getReferenceValue"); +vi.mock("./evaluateTemplate"); describe(evaluateExpression.name, () => { const mockOptions = { @@ -17,12 +19,12 @@ describe(evaluateExpression.name, () => { const mockResult = "mockResult"; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("calls evaluateTemplate if input is string", () => { const mockInput = "mockInput"; - (evaluateTemplate as jest.Mock).mockReturnValue(mockResult); + vi.mocked(evaluateTemplate).mockReturnValue(mockResult); const result = evaluateExpression(mockInput, mockKeyName, mockOptions); expect(result).toBe(mockResult); expect(evaluateTemplate).toHaveBeenCalledWith(mockInput, mockOptions); @@ -32,7 +34,7 @@ describe(evaluateExpression.name, () => { it("calls callFunction if input constains 'fn' key", () => { const mockInput = { fn: "fn", argv: ["arg1"] }; - (callFunction as jest.Mock).mockReturnValue(mockResult); + vi.mocked(callFunction).mockReturnValue(mockResult); const result = evaluateExpression(mockInput, mockKeyName, mockOptions); expect(result).toBe(mockResult); expect(evaluateTemplate).not.toHaveBeenCalled(); @@ -42,7 +44,7 @@ describe(evaluateExpression.name, () => { it("calls getReferenceValue if input constains 'ref' key", () => { const mockInput = { ref: "ref" }; - (getReferenceValue as jest.Mock).mockReturnValue(mockResult); + vi.mocked(getReferenceValue).mockReturnValue(mockResult); const result = evaluateExpression(mockInput, mockKeyName, mockOptions); expect(result).toBe(mockResult); expect(evaluateTemplate).not.toHaveBeenCalled(); diff --git a/packages/util-endpoints/src/utils/evaluateRules.spec.ts b/packages/util-endpoints/src/utils/evaluateRules.spec.ts index 1b79e6e8524..b99f16c9cfe 100644 --- a/packages/util-endpoints/src/utils/evaluateRules.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateRules.spec.ts @@ -1,12 +1,14 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { EndpointError, EndpointRuleObject, ErrorRuleObject, TreeRuleObject } from "../types"; import { evaluateEndpointRule } from "./evaluateEndpointRule"; import { evaluateErrorRule } from "./evaluateErrorRule"; import { evaluateRules } from "./evaluateRules"; import { evaluateTreeRule } from "./evaluateTreeRule"; -jest.mock("./evaluateEndpointRule"); -jest.mock("./evaluateErrorRule"); -jest.mock("./evaluateTreeRule"); +vi.mock("./evaluateEndpointRule"); +vi.mock("./evaluateErrorRule"); +vi.mock("./evaluateTreeRule"); describe(evaluateRules.name, () => { const mockOptions = { @@ -43,18 +45,18 @@ describe(evaluateRules.name, () => { const mockRules = [mockEndpointRule, mockErrorRule, mockTreeRule]; beforeEach(() => { - (evaluateEndpointRule as jest.Mock).mockReturnValue(undefined); - (evaluateErrorRule as jest.Mock).mockReturnValue(undefined); - (evaluateTreeRule as jest.Mock).mockReturnValue(undefined); + vi.mocked(evaluateEndpointRule).mockReturnValue(undefined); + vi.mocked(evaluateErrorRule).mockReturnValue(undefined); + vi.mocked(evaluateTreeRule).mockReturnValue(undefined); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); describe("returns endpoint if defined", () => { it("from EndPoint Rule", () => { - (evaluateEndpointRule as jest.Mock).mockReturnValue(mockEndpointResult); + vi.mocked(evaluateEndpointRule).mockReturnValue(mockEndpointResult); const result = evaluateRules(mockRules, mockOptions); expect(result).toEqual(mockEndpointResult); expect(evaluateEndpointRule).toHaveBeenCalledWith(mockEndpointRule, mockOptions); @@ -63,7 +65,7 @@ describe(evaluateRules.name, () => { }); it("from Tree Rule", () => { - (evaluateTreeRule as jest.Mock).mockReturnValue(mockEndpointResult); + vi.mocked(evaluateTreeRule).mockReturnValue(mockEndpointResult); const result = evaluateRules(mockRules, mockOptions); expect(result).toEqual(mockEndpointResult); expect(evaluateEndpointRule).toHaveBeenCalledWith(mockEndpointRule, mockOptions); @@ -74,7 +76,7 @@ describe(evaluateRules.name, () => { it("re-throws error from Error Rule, if it occurs before endpoint evaluation", () => { const mockError = new Error("mockError"); - (evaluateErrorRule as jest.Mock).mockImplementation(() => { + vi.mocked(evaluateErrorRule).mockImplementation(() => { throw mockError; }); expect(() => evaluateRules(mockRules, mockOptions)).toThrow(mockError); diff --git a/packages/util-endpoints/src/utils/evaluateTemplate.spec.ts b/packages/util-endpoints/src/utils/evaluateTemplate.spec.ts index 6fbeff935e3..9b1f024180a 100644 --- a/packages/util-endpoints/src/utils/evaluateTemplate.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateTemplate.spec.ts @@ -1,7 +1,9 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { getAttr } from "../lib"; import { evaluateTemplate } from "./evaluateTemplate"; -jest.mock("../lib"); +vi.mock("../lib"); describe(evaluateTemplate.name, () => { const mockOptions = { @@ -10,7 +12,7 @@ describe(evaluateTemplate.name, () => { }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should not escape template without braces", () => { @@ -43,8 +45,8 @@ describe(evaluateTemplate.name, () => { const ref1 = { key1: "value1" }; const ref2 = { key2: "value2" }; - (getAttr as jest.Mock).mockReturnValueOnce(ref1["key1"]); - (getAttr as jest.Mock).mockReturnValueOnce(ref2["key2"]); + vi.mocked(getAttr).mockReturnValueOnce(ref1["key1"]); + vi.mocked(getAttr).mockReturnValueOnce(ref2["key2"]); expect( evaluateTemplate("foo {ref1#key1} bar {ref2#key2} baz", { ...mockOptions, referenceRecord: { ref1, ref2 } }) diff --git a/packages/util-endpoints/src/utils/evaluateTreeRule.spec.ts b/packages/util-endpoints/src/utils/evaluateTreeRule.spec.ts index 72881e8a296..318339e209b 100644 --- a/packages/util-endpoints/src/utils/evaluateTreeRule.spec.ts +++ b/packages/util-endpoints/src/utils/evaluateTreeRule.spec.ts @@ -1,10 +1,12 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { TreeRuleObject } from "../types"; import { evaluateConditions } from "./evaluateConditions"; import { evaluateRules } from "./evaluateRules"; import { evaluateTreeRule } from "./evaluateTreeRule"; -jest.mock("./evaluateConditions"); -jest.mock("./evaluateRules"); +vi.mock("./evaluateConditions"); +vi.mock("./evaluateRules"); describe(evaluateTreeRule.name, () => { const mockOptions = { @@ -22,7 +24,7 @@ describe(evaluateTreeRule.name, () => { }; it("returns undefined if conditions evaluate to false", () => { - (evaluateConditions as jest.Mock).mockReturnValue({ result: false }); + vi.mocked(evaluateConditions).mockReturnValue({ result: false }); const result = evaluateTreeRule(mockTreeRule, mockOptions); expect(result).toBeUndefined(); expect(evaluateConditions).toHaveBeenCalledWith(mockConditions, mockOptions); @@ -33,8 +35,8 @@ describe(evaluateTreeRule.name, () => { const mockReferenceRecord = { key: "value" }; const mockEndpointUrl = new URL("http://example.com"); - (evaluateConditions as jest.Mock).mockReturnValue({ result: true, referenceRecord: mockReferenceRecord }); - (evaluateRules as jest.Mock).mockReturnValue(mockEndpointUrl); + vi.mocked(evaluateConditions).mockReturnValue({ result: true, referenceRecord: mockReferenceRecord }); + vi.mocked(evaluateRules).mockReturnValue(mockEndpointUrl); const result = evaluateTreeRule(mockTreeRule, mockOptions); expect(result).toBe(mockEndpointUrl); diff --git a/packages/util-endpoints/src/utils/getEndpointHeaders.spec.ts b/packages/util-endpoints/src/utils/getEndpointHeaders.spec.ts index 7b79f733b1b..9f2c354890d 100644 --- a/packages/util-endpoints/src/utils/getEndpointHeaders.spec.ts +++ b/packages/util-endpoints/src/utils/getEndpointHeaders.spec.ts @@ -1,7 +1,9 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { evaluateExpression } from "./evaluateExpression"; import { getEndpointHeaders } from "./getEndpointHeaders"; -jest.mock("./evaluateExpression"); +vi.mock("./evaluateExpression"); describe(getEndpointHeaders.name, () => { const mockOptions = { @@ -10,7 +12,7 @@ describe(getEndpointHeaders.name, () => { }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should return an empty object if empty headers are provided", () => { @@ -23,7 +25,7 @@ describe(getEndpointHeaders.name, () => { const outputHeaderValue = "outputHeaderValue"; const mockHeaders = { key: [inputHeaderValue] }; - (evaluateExpression as jest.Mock).mockReturnValue(outputHeaderValue); + vi.mocked(evaluateExpression).mockReturnValue(outputHeaderValue); expect(getEndpointHeaders(mockHeaders, mockOptions)).toEqual({ key: [outputHeaderValue] }); expect(evaluateExpression).toHaveBeenCalledWith("inputHeaderValue", "Header value entry", mockOptions); }); @@ -35,7 +37,7 @@ describe(getEndpointHeaders.name, () => { const inputHeaderValue = "inputHeaderValue"; const mockHeaders = { [inputHeaderKey]: [inputHeaderValue] }; - (evaluateExpression as jest.Mock).mockReturnValue(notStringValue); + vi.mocked(evaluateExpression).mockReturnValue(notStringValue); expect(() => getEndpointHeaders(mockHeaders, mockOptions)).toThrowError( `Header '${inputHeaderKey}' value '${notStringValue}' is not a string` ); diff --git a/packages/util-endpoints/src/utils/getEndpointProperties.spec.ts b/packages/util-endpoints/src/utils/getEndpointProperties.spec.ts index f751d157a2e..951c7a8d62f 100644 --- a/packages/util-endpoints/src/utils/getEndpointProperties.spec.ts +++ b/packages/util-endpoints/src/utils/getEndpointProperties.spec.ts @@ -1,7 +1,9 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { getEndpointProperties } from "./getEndpointProperties"; import { getEndpointProperty } from "./getEndpointProperty"; -jest.mock("./getEndpointProperty"); +vi.mock("./getEndpointProperty"); describe(getEndpointProperties.name, () => { const mockOptions = { @@ -10,7 +12,7 @@ describe(getEndpointProperties.name, () => { }; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should return an empty object if empty properties are provided", () => { @@ -22,7 +24,7 @@ describe(getEndpointProperties.name, () => { const outputPropertyValue = "outputPropertyValue"; const mockProperties = { key: inputPropertyValue }; - (getEndpointProperty as jest.Mock).mockReturnValue(outputPropertyValue); + vi.mocked(getEndpointProperty).mockReturnValue(outputPropertyValue); expect(getEndpointProperties(mockProperties, mockOptions)).toEqual({ key: outputPropertyValue }); expect(getEndpointProperty).toHaveBeenCalledWith(inputPropertyValue, mockOptions); }); diff --git a/packages/util-endpoints/src/utils/getEndpointProperty.spec.ts b/packages/util-endpoints/src/utils/getEndpointProperty.spec.ts index ebf8af3d76a..a36344a2345 100644 --- a/packages/util-endpoints/src/utils/getEndpointProperty.spec.ts +++ b/packages/util-endpoints/src/utils/getEndpointProperty.spec.ts @@ -1,10 +1,12 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { EndpointError } from "../types"; import { evaluateTemplate } from "./evaluateTemplate"; import { getEndpointProperties } from "./getEndpointProperties"; import { getEndpointProperty } from "./getEndpointProperty"; -jest.mock("./evaluateTemplate"); -jest.mock("./getEndpointProperties"); +vi.mock("./evaluateTemplate"); +vi.mock("./getEndpointProperties"); describe(getEndpointProperty.name, () => { const mockOptions = { @@ -19,12 +21,12 @@ describe(getEndpointProperty.name, () => { const mockBoolean = false; beforeEach(() => { - (evaluateTemplate as jest.Mock).mockReturnValue(mockOutputString); - (getEndpointProperties as jest.Mock).mockReturnValue(mockOutputObject); + vi.mocked(evaluateTemplate).mockReturnValue(mockOutputString); + vi.mocked(getEndpointProperties).mockReturnValue(mockOutputObject); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("processes each property in an array", () => { diff --git a/packages/util-endpoints/src/utils/getEndpointUrl.spec.ts b/packages/util-endpoints/src/utils/getEndpointUrl.spec.ts index 3ef27c66dcc..9752145b382 100644 --- a/packages/util-endpoints/src/utils/getEndpointUrl.spec.ts +++ b/packages/util-endpoints/src/utils/getEndpointUrl.spec.ts @@ -1,8 +1,10 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { EndpointError } from "../types"; import { evaluateExpression } from "./evaluateExpression"; import { getEndpointUrl } from "./getEndpointUrl"; -jest.mock("./evaluateExpression"); +vi.mock("./evaluateExpression"); describe(getEndpointUrl.name, () => { const mockEndpointUrlInput = "http://input.example.com"; @@ -13,7 +15,7 @@ describe(getEndpointUrl.name, () => { }; it("returns URL is expression evaluates to string", () => { - (evaluateExpression as jest.Mock).mockReturnValue(mockEndpointUrlOutput); + vi.mocked(evaluateExpression).mockReturnValue(mockEndpointUrlOutput); const result = getEndpointUrl(mockEndpointUrlInput, mockOptions); expect(result).toEqual(new URL(mockEndpointUrlOutput)); expect(evaluateExpression).toHaveBeenCalledWith(mockEndpointUrlInput, "Endpoint URL", mockOptions); @@ -21,7 +23,7 @@ describe(getEndpointUrl.name, () => { it("throws error if expression evaluates to non-string", () => { const mockNotStringOutput = 42; - (evaluateExpression as jest.Mock).mockReturnValue(mockNotStringOutput); + vi.mocked(evaluateExpression).mockReturnValue(mockNotStringOutput); expect(() => getEndpointUrl(mockEndpointUrlInput, mockOptions)).toThrowError( new EndpointError(`Endpoint URL must be a string, got ${typeof mockNotStringOutput}`) ); diff --git a/packages/util-endpoints/src/utils/getReferenceValue.spec.ts b/packages/util-endpoints/src/utils/getReferenceValue.spec.ts index e881760d65c..5201e5b09ca 100644 --- a/packages/util-endpoints/src/utils/getReferenceValue.spec.ts +++ b/packages/util-endpoints/src/utils/getReferenceValue.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, describe, expect, test as it, vi } from "vitest"; + import { getReferenceValue } from "./getReferenceValue"; describe(getReferenceValue.name, () => { @@ -9,7 +11,7 @@ describe(getReferenceValue.name, () => { const mockRefValue = "mockRefValue"; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("returns reference value if reference exists", () => { diff --git a/packages/util-endpoints/vitest.config.integ.ts b/packages/util-endpoints/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/util-endpoints/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-endpoints/vitest.config.ts b/packages/util-endpoints/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-endpoints/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-hex-encoding/jest.config.js b/packages/util-hex-encoding/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-hex-encoding/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-hex-encoding/package.json b/packages/util-hex-encoding/package.json index c14cacc6ce4..92ab39c81a1 100644 --- a/packages/util-hex-encoding/package.json +++ b/packages/util-hex-encoding/package.json @@ -12,7 +12,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-hex-encoding/src/index.spec.ts b/packages/util-hex-encoding/src/index.spec.ts index f99f897ad04..7645b8384a2 100644 --- a/packages/util-hex-encoding/src/index.spec.ts +++ b/packages/util-hex-encoding/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { fromHex, toHex } from "./"; const encoded = "dead" + "beef" + "cafe" + "babe" + "face"; diff --git a/packages/util-hex-encoding/vitest.config.ts b/packages/util-hex-encoding/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-hex-encoding/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-middleware/jest.config.js b/packages/util-middleware/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-middleware/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-middleware/package.json b/packages/util-middleware/package.json index 4e8b2cb1000..683f87b663a 100644 --- a/packages/util-middleware/package.json +++ b/packages/util-middleware/package.json @@ -14,7 +14,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "keywords": [ "aws", diff --git a/packages/util-middleware/src/normalizeProvider.spec.ts b/packages/util-middleware/src/normalizeProvider.spec.ts index 8650d6f0b24..dd95bd05ab2 100644 --- a/packages/util-middleware/src/normalizeProvider.spec.ts +++ b/packages/util-middleware/src/normalizeProvider.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { normalizeProvider } from "./normalizeProvider"; describe(normalizeProvider.name, () => { diff --git a/packages/util-middleware/vitest.config.ts b/packages/util-middleware/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-middleware/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-retry/jest.config.js b/packages/util-retry/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-retry/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-retry/package.json b/packages/util-retry/package.json index 299988fd8d4..e59f492a067 100644 --- a/packages/util-retry/package.json +++ b/packages/util-retry/package.json @@ -15,7 +15,8 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "keywords": [ "aws", diff --git a/packages/util-retry/src/AdaptiveRetryStrategy.spec.ts b/packages/util-retry/src/AdaptiveRetryStrategy.spec.ts index 16449a35b8a..e6d54ad7b1b 100644 --- a/packages/util-retry/src/AdaptiveRetryStrategy.spec.ts +++ b/packages/util-retry/src/AdaptiveRetryStrategy.spec.ts @@ -1,4 +1,5 @@ import { RetryErrorInfo, StandardRetryToken } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { AdaptiveRetryStrategy } from "./AdaptiveRetryStrategy"; import { RETRY_MODES } from "./config"; @@ -6,15 +7,15 @@ import { DefaultRateLimiter } from "./DefaultRateLimiter"; import { StandardRetryStrategy } from "./StandardRetryStrategy"; import { RateLimiter } from "./types"; -jest.mock("./StandardRetryStrategy"); -jest.mock("./DefaultRateLimiter"); +vi.mock("./StandardRetryStrategy"); +vi.mock("./DefaultRateLimiter"); describe(AdaptiveRetryStrategy.name, () => { - const maxAttemptsProvider = jest.fn(); + const maxAttemptsProvider = vi.fn(); const retryTokenScope = "scope"; const mockDefaultRateLimiter = { - getSendToken: jest.fn(), - updateClientSendingRate: jest.fn(), + getSendToken: vi.fn(), + updateClientSendingRate: vi.fn(), }; const mockRetryToken: StandardRetryToken = { getRetryCost: () => 1, @@ -26,11 +27,11 @@ describe(AdaptiveRetryStrategy.name, () => { } as RetryErrorInfo; beforeEach(() => { - (DefaultRateLimiter as jest.Mock).mockReturnValue(mockDefaultRateLimiter); + vi.mocked(DefaultRateLimiter).mockReturnValue(mockDefaultRateLimiter); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it(`sets mode=${RETRY_MODES.ADAPTIVE}`, () => { @@ -60,7 +61,7 @@ describe(AdaptiveRetryStrategy.name, () => { describe("acquireInitialRetryToken", () => { it("calls rateLimiter.getSendToken and returns initial retry token ", async () => { - const mockedStandardRetryStrategy = jest.spyOn(StandardRetryStrategy.prototype, "acquireInitialRetryToken"); + const mockedStandardRetryStrategy = vi.spyOn(StandardRetryStrategy.prototype, "acquireInitialRetryToken"); mockedStandardRetryStrategy.mockResolvedValue(mockRetryToken); const retryStrategy = new AdaptiveRetryStrategy(maxAttemptsProvider, { rateLimiter: mockDefaultRateLimiter, @@ -73,7 +74,7 @@ describe(AdaptiveRetryStrategy.name, () => { }); describe("refreshRetryTokenForRetry", () => { it("calls rateLimiter.updateCientSendingRate and refreshes retry token", async () => { - const mockedStandardRetryStrategy = jest.spyOn(StandardRetryStrategy.prototype, "refreshRetryTokenForRetry"); + const mockedStandardRetryStrategy = vi.spyOn(StandardRetryStrategy.prototype, "refreshRetryTokenForRetry"); mockedStandardRetryStrategy.mockResolvedValue(mockRetryToken); const retryStrategy = new AdaptiveRetryStrategy(maxAttemptsProvider, { rateLimiter: mockDefaultRateLimiter, @@ -88,7 +89,7 @@ describe(AdaptiveRetryStrategy.name, () => { }); describe("recordSuccess", () => { it("rateLimiter.updateCientSendingRate and records success on token", async () => { - const mockedStandardRetryStrategy = jest.spyOn(StandardRetryStrategy.prototype, "recordSuccess"); + const mockedStandardRetryStrategy = vi.spyOn(StandardRetryStrategy.prototype, "recordSuccess"); const retryStrategy = new AdaptiveRetryStrategy(maxAttemptsProvider, { rateLimiter: mockDefaultRateLimiter, }); diff --git a/packages/util-retry/src/ConfiguredRetryStrategy.spec.ts b/packages/util-retry/src/ConfiguredRetryStrategy.spec.ts index 9a1dd3ea3a8..7b54c418280 100644 --- a/packages/util-retry/src/ConfiguredRetryStrategy.spec.ts +++ b/packages/util-retry/src/ConfiguredRetryStrategy.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { ConfiguredRetryStrategy } from "./ConfiguredRetryStrategy"; describe(ConfiguredRetryStrategy.name, () => { diff --git a/packages/util-retry/src/DefaultRateLimiter.spec.ts b/packages/util-retry/src/DefaultRateLimiter.spec.ts index 39c375b17c3..45c5b34753d 100644 --- a/packages/util-retry/src/DefaultRateLimiter.spec.ts +++ b/packages/util-retry/src/DefaultRateLimiter.spec.ts @@ -1,25 +1,26 @@ import { isThrottlingError } from "@smithy/service-error-classification"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { DefaultRateLimiter } from "./DefaultRateLimiter"; -jest.mock("@smithy/service-error-classification"); +vi.mock("@smithy/service-error-classification"); describe(DefaultRateLimiter.name, () => { beforeEach(() => { - (isThrottlingError as jest.Mock).mockReturnValue(false); + vi.mocked(isThrottlingError).mockReturnValue(false); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("getSendToken", () => { beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it.each([ @@ -27,16 +28,17 @@ describe(DefaultRateLimiter.name, () => { [1, 1785.7142857142856], [2, 2000], ])("timestamp: %d, delay: %d", async (timestamp, delay) => { - jest.spyOn(Date, "now").mockImplementation(() => 0); + const spy = vi.spyOn(DefaultRateLimiter as any, "setTimeoutFn"); + vi.spyOn(Date, "now").mockImplementation(() => 0); const rateLimiter = new DefaultRateLimiter(); - (isThrottlingError as jest.Mock).mockReturnValueOnce(true); - jest.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); + vi.mocked(isThrottlingError).mockReturnValueOnce(true); + vi.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); rateLimiter.updateClientSendingRate({}); rateLimiter.getSendToken(); - jest.runAllTimers(); - expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), delay); + vi.runAllTimers(); + expect(spy).toHaveBeenLastCalledWith(expect.any(Function), delay); }); }); @@ -50,14 +52,14 @@ describe(DefaultRateLimiter.name, () => { [10, 21.26626836], [11, 36.42599853], ])("timestamp: %d, calculatedRate: %d", (timestamp, calculatedRate) => { - jest.spyOn(Date, "now").mockImplementation(() => 0); + vi.spyOn(Date, "now").mockImplementation(() => 0); const rateLimiter = new DefaultRateLimiter(); rateLimiter["lastMaxRate"] = 10; rateLimiter["lastThrottleTime"] = 5; - jest.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); + vi.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); - const cubicSuccessSpy = jest.spyOn(DefaultRateLimiter.prototype as any, "cubicSuccess"); + const cubicSuccessSpy = vi.spyOn(DefaultRateLimiter.prototype as any, "cubicSuccess"); rateLimiter.updateClientSendingRate({}); expect(cubicSuccessSpy).toHaveLastReturnedWith(calculatedRate); }); @@ -71,21 +73,21 @@ describe(DefaultRateLimiter.name, () => { [8, 0.07], [9, 0.06222222], ])("timestamp: %d, calculatedRate: %d", (timestamp, calculatedRate) => { - jest.spyOn(Date, "now").mockImplementation(() => 0); + vi.spyOn(Date, "now").mockImplementation(() => 0); const rateLimiter = new DefaultRateLimiter(); rateLimiter["lastMaxRate"] = 10; rateLimiter["lastThrottleTime"] = 5; - (isThrottlingError as jest.Mock).mockReturnValueOnce(true); - jest.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); - const cubicThrottleSpy = jest.spyOn(DefaultRateLimiter.prototype as any, "cubicThrottle"); + vi.mocked(isThrottlingError).mockReturnValueOnce(true); + vi.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); + const cubicThrottleSpy = vi.spyOn(DefaultRateLimiter.prototype as any, "cubicThrottle"); rateLimiter.updateClientSendingRate({}); expect(cubicThrottleSpy).toHaveLastReturnedWith(calculatedRate); }); }); it("updateClientSendingRate", () => { - jest.spyOn(Date, "now").mockImplementation(() => 0); + vi.spyOn(Date, "now").mockImplementation(() => 0); const rateLimiter = new DefaultRateLimiter(); const testCases: [boolean, number, number, number][] = [ @@ -109,8 +111,8 @@ describe(DefaultRateLimiter.name, () => { ]; testCases.forEach(([isThrottlingErrorReturn, timestamp, measuredTxRate, fillRate]) => { - (isThrottlingError as jest.Mock).mockReturnValue(isThrottlingErrorReturn); - jest.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); + vi.mocked(isThrottlingError).mockReturnValue(isThrottlingErrorReturn); + vi.spyOn(Date, "now").mockImplementation(() => timestamp * 1000); rateLimiter.updateClientSendingRate({}); expect(rateLimiter["measuredTxRate"]).toEqual(measuredTxRate); diff --git a/packages/util-retry/src/DefaultRateLimiter.ts b/packages/util-retry/src/DefaultRateLimiter.ts index ed3ef8427f8..f450fb91d77 100644 --- a/packages/util-retry/src/DefaultRateLimiter.ts +++ b/packages/util-retry/src/DefaultRateLimiter.ts @@ -17,6 +17,11 @@ export interface DefaultRateLimiterOptions { * @public */ export class DefaultRateLimiter implements RateLimiter { + /** + * Only used in testing. + */ + private static setTimeoutFn = setTimeout; + // User configurable constants private beta: number; private minCapacity: number; @@ -71,7 +76,7 @@ export class DefaultRateLimiter implements RateLimiter { this.refillTokenBucket(); if (amount > this.currentCapacity) { const delay = ((amount - this.currentCapacity) / this.fillRate) * 1000; - await new Promise((resolve) => setTimeout(resolve, delay)); + await new Promise((resolve) => DefaultRateLimiter.setTimeoutFn(resolve, delay)); } this.currentCapacity = this.currentCapacity - amount; } diff --git a/packages/util-retry/src/StandardRetryStrategy.spec.ts b/packages/util-retry/src/StandardRetryStrategy.spec.ts index 3ccb144828f..d8b3a4dff6a 100644 --- a/packages/util-retry/src/StandardRetryStrategy.spec.ts +++ b/packages/util-retry/src/StandardRetryStrategy.spec.ts @@ -1,12 +1,13 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { RetryErrorInfo, RetryErrorType } from "@smithy/types"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { RETRY_MODES } from "./config"; import { DEFAULT_RETRY_DELAY_BASE } from "./constants"; import { createDefaultRetryToken } from "./defaultRetryToken"; import { StandardRetryStrategy } from "./StandardRetryStrategy"; -jest.mock("./defaultRetryToken"); +vi.mock("./defaultRetryToken"); describe(StandardRetryStrategy.name, () => { const maxAttempts = 3; @@ -19,11 +20,11 @@ describe(StandardRetryStrategy.name, () => { const errorInfo = { errorType: "TRANSIENT" } as RetryErrorInfo; beforeEach(() => { - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("sets maxAttemptsProvider as a class member variable", () => { @@ -53,13 +54,13 @@ describe(StandardRetryStrategy.name, () => { describe("refreshRetryTokenForRetry", () => { it("refreshes the token", async () => { - const getRetryCount = jest.fn().mockReturnValue(0); - const hasRetryTokens = jest.fn().mockReturnValue(true); + const getRetryCount = vi.fn().mockReturnValue(0); + const hasRetryTokens = vi.fn().mockReturnValue(true); const mockRetryToken = { getRetryCount, hasRetryTokens, }; - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts)); const token = await retryStrategy.acquireInitialRetryToken(retryTokenScope); await retryStrategy.refreshRetryTokenForRetry(token, errorInfo); @@ -71,7 +72,7 @@ describe(StandardRetryStrategy.name, () => { getRetryCount: () => 0, getRetryTokenCount: (errorInfo: any) => 1, }; - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); const retryStrategy = new StandardRetryStrategy(1); const token = await retryStrategy.acquireInitialRetryToken(retryTokenScope); try { @@ -87,7 +88,7 @@ describe(StandardRetryStrategy.name, () => { getRetryCount: () => 2, getRetryTokenCount: (errorInfo: any) => 1, }; - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(1)); const token = await retryStrategy.acquireInitialRetryToken(retryTokenScope); try { @@ -103,7 +104,7 @@ describe(StandardRetryStrategy.name, () => { getRetryCount: () => 5, getRetryTokenCount: (errorInfo: any) => 1, }; - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(5)); const token = await retryStrategy.acquireInitialRetryToken(retryTokenScope); try { @@ -120,7 +121,7 @@ describe(StandardRetryStrategy.name, () => { getRetryTokenCount: (errorInfo: any) => 1, hasRetryTokens: (errorType: RetryErrorType) => true, }; - (createDefaultRetryToken as jest.Mock).mockReturnValue(mockRetryToken); + vi.mocked(createDefaultRetryToken).mockReturnValue(mockRetryToken); const retryStrategy = new StandardRetryStrategy(() => Promise.resolve(maxAttempts)); const token = await retryStrategy.acquireInitialRetryToken(retryTokenScope); const errorInfo = { diff --git a/packages/util-retry/src/defaultRetryBackoffStrategy.spec.ts b/packages/util-retry/src/defaultRetryBackoffStrategy.spec.ts index dc0af34aed9..7be3a5967a0 100644 --- a/packages/util-retry/src/defaultRetryBackoffStrategy.spec.ts +++ b/packages/util-retry/src/defaultRetryBackoffStrategy.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { DEFAULT_RETRY_DELAY_BASE, MAXIMUM_RETRY_DELAY } from "./constants"; import { getDefaultRetryBackoffStrategy } from "./defaultRetryBackoffStrategy"; @@ -5,7 +7,7 @@ describe("defaultRetryBackoffStrategy", () => { const mathDotRandom = Math.random; beforeEach(() => { - Math.random = jest.fn().mockReturnValue(1); + Math.random = vi.fn().mockReturnValue(1); }); afterEach(() => { @@ -59,7 +61,7 @@ describe("defaultRetryBackoffStrategy", () => { const expectedDelay = Math.floor(mockRandomValue * 2 ** attempts * delayBase); retryBackoffStrategy.setDelayBase(delayBase); it(`(${delayBase}, ${attempts}) with mock Math.random=${mockRandomValue} returns ${expectedDelay}`, () => { - Math.random = jest.fn().mockReturnValue(mockRandomValue); + Math.random = vi.fn().mockReturnValue(mockRandomValue); expect(retryBackoffStrategy.computeNextBackoffDelay(attempts)).toBe(expectedDelay); }); }); diff --git a/packages/util-retry/src/defaultRetryToken.spec.ts b/packages/util-retry/src/defaultRetryToken.spec.ts index e0604d4a79c..b565dfe67b4 100644 --- a/packages/util-retry/src/defaultRetryToken.spec.ts +++ b/packages/util-retry/src/defaultRetryToken.spec.ts @@ -1,7 +1,9 @@ +import { describe, expect, test as it, vi } from "vitest"; + import { DEFAULT_RETRY_DELAY_BASE, MAXIMUM_RETRY_DELAY } from "./constants"; import { createDefaultRetryToken } from "./defaultRetryToken"; -jest.mock("./defaultRetryBackoffStrategy"); +vi.mock("./defaultRetryBackoffStrategy"); describe("defaultRetryToken", () => { describe("getRetryCost", () => { diff --git a/packages/util-retry/vitest.config.ts b/packages/util-retry/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-retry/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-stream-browser/README.md b/packages/util-stream-browser/README.md index 70d60656dc0..c96d33e5a7d 100644 --- a/packages/util-stream-browser/README.md +++ b/packages/util-stream-browser/README.md @@ -9,4 +9,4 @@ Package with utilities to operate on browser streams. ## Usage -You probably shouldn't, at least directly. +This package is deprecated for `@smithy/util-stream`, which provides the same functionality merging Node.js and browser. diff --git a/packages/util-stream-browser/jest.config.js b/packages/util-stream-browser/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-stream-browser/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-stream-browser/package.json b/packages/util-stream-browser/package.json index caaa3cd7519..2bf5a046484 100644 --- a/packages/util-stream-browser/package.json +++ b/packages/util-stream-browser/package.json @@ -10,7 +10,6 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest", "build:cjs": "node ../../scripts/inline util-stream-browser" }, "main": "./dist-es/index.js", diff --git a/packages/util-stream-browser/src/sdk-stream-mixin.spec.ts b/packages/util-stream-browser/src/sdk-stream-mixin.spec.ts deleted file mode 100644 index 9dc1e25f9ec..00000000000 --- a/packages/util-stream-browser/src/sdk-stream-mixin.spec.ts +++ /dev/null @@ -1,228 +0,0 @@ -// @jest-environment jsdom -import { streamCollector } from "@smithy/fetch-http-handler"; -import { SdkStreamMixin } from "@smithy/types"; -import { toBase64 } from "@smithy/util-base64"; -import { toHex } from "@smithy/util-hex-encoding"; -import { toUtf8 } from "@smithy/util-utf8"; - -import { sdkStreamMixin } from "./sdk-stream-mixin"; - -jest.mock("@smithy/fetch-http-handler"); -jest.mock("@smithy/util-base64"); -jest.mock("@smithy/util-hex-encoding"); -jest.mock("@smithy/util-utf8"); - -const mockStreamCollectorReturn = Uint8Array.from([117, 112, 113]); -(streamCollector as jest.Mock).mockReturnValue(mockStreamCollectorReturn); -Object.defineProperty(global, "Blob", { - writable: true, -}); -Object.defineProperty(global, "ReadableStream", { - writable: true, -}); - -describe(sdkStreamMixin.name, () => { - const expectAllTransformsToFail = async (sdkStream: SdkStreamMixin) => { - const transformMethods: Array = [ - "transformToByteArray", - "transformToString", - "transformToWebStream", - ]; - for (const method of transformMethods) { - try { - await sdkStream[method](); - fail(new Error("expect subsequent tranform to fail")); - } catch (error) { - expect(error.message).toContain("The stream has already been transformed"); - } - } - }; - - let originalReadableStreamCtr = global.ReadableStream; - const mockReadableStream = jest.fn(); - class ReadableStream { - constructor() { - mockReadableStream(); - } - } - - let payloadStream: ReadableStream; - - beforeAll(() => { - global.ReadableStream = ReadableStream as any; - }); - - beforeEach(() => { - originalReadableStreamCtr = global.ReadableStream; - jest.clearAllMocks(); - payloadStream = new ReadableStream(); - }); - - afterEach(() => { - global.ReadableStream = originalReadableStreamCtr; - }); - - it("should throw if input stream is not a Blob or Web Stream instance", () => { - const originalBlobCtr = global.Blob; - global.Blob = undefined; - global.ReadableStream = undefined; - try { - sdkStreamMixin({}); - fail("expect unexpected stream to fail"); - } catch (e) { - expect(e.message).toContain("nexpected stream implementation"); - global.Blob = originalBlobCtr; - } - }); - - describe("transformToByteArray", () => { - it("should transform binary stream to byte array", async () => { - const sdkStream = sdkStreamMixin(payloadStream); - const byteArray = await sdkStream.transformToByteArray(); - expect(streamCollector as jest.Mock).toBeCalledWith(payloadStream); - expect(byteArray).toEqual(mockStreamCollectorReturn); - }); - - it("should fail any subsequent tranform calls", async () => { - const sdkStream = sdkStreamMixin(payloadStream); - await sdkStream.transformToByteArray(); - await expectAllTransformsToFail(sdkStream); - }); - }); - - describe("transformToString", () => { - let originalTextDecoder = global.TextDecoder; - const mockDecode = jest.fn(); - global.TextDecoder = jest.fn().mockImplementation(function () { - return { decode: mockDecode }; - }); - - beforeEach(() => { - originalTextDecoder = global.TextDecoder; - jest.clearAllMocks(); - }); - - afterEach(() => { - global.TextDecoder = originalTextDecoder; - }); - - it.each([ - [undefined, toUtf8], - ["utf8", toUtf8], - ["utf-8", toUtf8], - ["base64", toBase64], - ["hex", toHex], - ])("should transform to string with %s encoding", async (encoding, encodingFn) => { - const mockEncodedStringValue = `a string with ${encoding} encoding`; - (encodingFn as jest.Mock).mockReturnValueOnce(mockEncodedStringValue); - const sdkStream = sdkStreamMixin(payloadStream); - const str = await sdkStream.transformToString(encoding); - expect(streamCollector).toBeCalled(); - expect(encodingFn).toBeCalledWith(mockStreamCollectorReturn); - expect(str).toEqual(mockEncodedStringValue); - }); - - it("should use TexDecoder to handle other encodings", async () => { - const utfLabel = "windows-1251"; - mockDecode.mockReturnValue(`a string with ${utfLabel} encoding`); - const sdkStream = sdkStreamMixin(payloadStream); - const str = await sdkStream.transformToString(utfLabel); - expect(global.TextDecoder).toBeCalledWith(utfLabel); - expect(str).toEqual(`a string with ${utfLabel} encoding`); - }); - - it("should throw if TextDecoder is not available", async () => { - global.TextDecoder = null; - const utfLabel = "windows-1251"; - const sdkStream = sdkStreamMixin(payloadStream); - try { - await sdkStream.transformToString(utfLabel); - fail("expect transformToString to throw when TextDecoder is not available"); - } catch (error) { - expect(error.message).toContain("TextDecoder is not available"); - } - }); - - it("should fail any subsequent tranform calls", async () => { - const sdkStream = sdkStreamMixin(payloadStream); - await sdkStream.transformToString(); - await expectAllTransformsToFail(sdkStream); - }); - }); - - describe("transformToWebStream with ReadableStream payload", () => { - it("should return the payload if it is Web Stream instance", () => { - const payloadStream = new ReadableStream(); - const sdkStream = sdkStreamMixin(payloadStream as any); - const transformed = sdkStream.transformToWebStream(); - expect(transformed).toBe(payloadStream); - }); - - it("should fail any subsequent tranform calls", async () => { - const payloadStream = new ReadableStream(); - const sdkStream = sdkStreamMixin(payloadStream as any); - sdkStream.transformToWebStream(); - await expectAllTransformsToFail(sdkStream); - }); - }); - - describe("transformToWebStream with Blob payload", () => { - let originalBlobCtr = global.Blob; - const mockBlob = jest.fn(); - const mockBlobStream = jest.fn(); - class Blob { - constructor() { - mockBlob(); - } - - stream() { - return mockBlobStream(); - } - } - global.Blob = Blob as any; - - beforeEach(() => { - global.ReadableStream = undefined; - originalBlobCtr = global.Blob; - jest.clearAllMocks(); - }); - - afterEach(() => { - global.Blob = originalBlobCtr; - }); - - it("should transform blob to web stream with Blob.stream()", () => { - mockBlobStream.mockReturnValue("transformed"); - const payloadStream = new Blob(); - const sdkStream = sdkStreamMixin(payloadStream as any); - const transformed = sdkStream.transformToWebStream(); - expect(transformed).toBe("transformed"); - expect(mockBlobStream).toBeCalled(); - }); - - it("should fail if Blob.stream() is not available", async () => { - class Blob { - constructor() { - mockBlob(); - } - } - - global.Blob = Blob as any; - const payloadStream = new Blob(); - const sdkStream = sdkStreamMixin(payloadStream as any); - try { - sdkStream.transformToWebStream(); - fail("expect to fail"); - } catch (e) { - expect(e.message).toContain("Please make sure the Blob.stream() is polyfilled"); - } - }); - - it("should fail any subsequent tranform calls", async () => { - const payloadStream = new Blob(); - const sdkStream = sdkStreamMixin(payloadStream as any); - sdkStream.transformToWebStream(); - await expectAllTransformsToFail(sdkStream); - }); - }); -}); diff --git a/packages/util-stream-node/README.md b/packages/util-stream-node/README.md index c7e9bf64b9f..226c2b65a50 100644 --- a/packages/util-stream-node/README.md +++ b/packages/util-stream-node/README.md @@ -9,4 +9,4 @@ Package with utilities to operate on Node.JS streams. ## Usage -You probably shouldn't, at least directly. +This package is deprecated for `@smithy/util-stream`, which provides the same functionality merging Node.js and browser. diff --git a/packages/util-stream-node/jest.config.js b/packages/util-stream-node/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-stream-node/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-stream-node/package.json b/packages/util-stream-node/package.json index fcf19a5cee0..e2c73aacfea 100644 --- a/packages/util-stream-node/package.json +++ b/packages/util-stream-node/package.json @@ -10,8 +10,7 @@ "stage-release": "rimraf ./.release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", - "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-stream-node/src/getAwsChunkedEncodingStream.spec.ts b/packages/util-stream-node/src/getAwsChunkedEncodingStream.spec.ts deleted file mode 100644 index d593a5db742..00000000000 --- a/packages/util-stream-node/src/getAwsChunkedEncodingStream.spec.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Readable } from "stream"; - -import { getAwsChunkedEncodingStream } from "./getAwsChunkedEncodingStream"; - -describe(getAwsChunkedEncodingStream.name, () => { - const mockBase64Encoder = jest.fn(); - const mockBodyLengthChecker = jest.fn(); - const mockChecksumAlgorithmFn = jest.fn(); - const mockChecksumLocationName = "mockChecksumLocationName"; - const mockStreamHasher = jest.fn(); - - const mockOptions = { - base64Encoder: mockBase64Encoder, - bodyLengthChecker: mockBodyLengthChecker, - checksumAlgorithmFn: mockChecksumAlgorithmFn, - checksumLocationName: mockChecksumLocationName, - streamHasher: mockStreamHasher, - }; - - const mockChecksum = "mockChecksum"; - const mockRawChecksum = Buffer.from(mockChecksum); - const mockStreamChunks = ["Hello", "World"]; - const mockBodyLength = 5; - - const getMockReadableStream = () => { - const readableStream = new Readable(); - mockStreamChunks.forEach((chunk) => { - readableStream.push(chunk); - }); - readableStream.push(null); - return readableStream; - }; - - beforeEach(() => { - mockStreamHasher.mockResolvedValue(mockRawChecksum); - mockBase64Encoder.mockReturnValue(mockChecksum); - mockBodyLengthChecker.mockReturnValue(mockBodyLength); - }); - - afterEach(() => { - expect(mockBodyLengthChecker).toHaveBeenCalledTimes(mockStreamChunks.length); - mockStreamChunks.forEach((chunk, index) => { - expect(mockBodyLengthChecker).toHaveBeenNthCalledWith(index + 1, Buffer.from(chunk)); - }); - jest.clearAllMocks(); - }); - - describe("skips checksum computation", () => { - const validateStreamWithoutChecksum = (awsChunkedEncodingStream: Readable, done: Function) => { - let buffer = ""; - awsChunkedEncodingStream.on("data", (data) => { - buffer += data.toString(); - }); - awsChunkedEncodingStream.on("end", () => { - expect(mockStreamHasher).not.toHaveBeenCalled(); - expect(mockBase64Encoder).not.toHaveBeenCalled(); - expect(buffer).toEqual(`5\r -Hello\r -5\r -World\r -0\r -`); - done(); - }); - }; - - it("if none of the required options are passed", (done) => { - const readableStream = getMockReadableStream(); - const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, { - bodyLengthChecker: mockBodyLengthChecker, - }); - validateStreamWithoutChecksum(awsChunkedEncodingStream, done); - }); - - ["base64Encoder", "checksumAlgorithmFn", "checksumLocationName", "streamHasher"].forEach((optionToRemove) => { - it(`if option '${optionToRemove}' is not passed`, (done) => { - const readableStream = getMockReadableStream(); - const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, { - ...mockOptions, - [optionToRemove]: undefined, - }); - validateStreamWithoutChecksum(awsChunkedEncodingStream, done); - }); - }); - }); - - it("computes checksum and adds it to the end event", (done) => { - const readableStream = getMockReadableStream(); - const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, mockOptions); - - let buffer = ""; - awsChunkedEncodingStream.on("data", (data) => { - buffer += data.toString(); - }); - awsChunkedEncodingStream.on("end", () => { - expect(mockStreamHasher).toHaveBeenCalledWith(mockChecksumAlgorithmFn, readableStream); - expect(mockBase64Encoder).toHaveBeenCalledWith(mockRawChecksum); - expect(buffer).toStrictEqual(`5\r -Hello\r -5\r -World\r -0\r -mockChecksumLocationName:mockChecksum\r -\r -`); - done(); - }); - }); -}); diff --git a/packages/util-stream-node/src/sdk-stream-mixin.spec.ts b/packages/util-stream-node/src/sdk-stream-mixin.spec.ts deleted file mode 100644 index 654a9c664b2..00000000000 --- a/packages/util-stream-node/src/sdk-stream-mixin.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { SdkStreamMixin } from "@smithy/types"; -import { fromArrayBuffer } from "@smithy/util-buffer-from"; -import { PassThrough, Readable, Writable } from "stream"; -import util from "util"; - -import { sdkStreamMixin } from "./sdk-stream-mixin"; - -jest.mock("@smithy/util-buffer-from"); - -describe(sdkStreamMixin.name, () => { - const writeDataToStream = (stream: Writable, data: Array): Promise => - new Promise((resolve, reject) => { - data.forEach((chunk) => { - stream.write(chunk, (err) => { - if (err) reject(err); - }); - }); - stream.end(resolve); - }); - const byteArrayFromBuffer = (buf: Buffer) => new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); - let passThrough: PassThrough; - const expectAllTransformsToFail = async (sdkStream: SdkStreamMixin) => { - const transformMethods: Array = [ - "transformToByteArray", - "transformToString", - "transformToWebStream", - ]; - for (const method of transformMethods) { - try { - await sdkStream[method](); - fail(new Error("expect subsequent tranform to fail")); - } catch (error) { - expect(error.message).toContain("The stream has already been transformed"); - } - } - }; - - beforeEach(() => { - passThrough = new PassThrough(); - }); - - it("should throw if unexpected stream implementation is supplied", () => { - try { - const payload = {}; - sdkStreamMixin(payload); - fail("should throw when unexpected stream is supplied"); - } catch (error) { - expect(error.message).toContain("Unexpected stream implementation"); - } - }); - - describe("transformToByteArray", () => { - it("should transform binary stream to byte array", async () => { - const mockData = [Buffer.from("foo"), Buffer.from("bar"), Buffer.from("buzz")]; - const expected = byteArrayFromBuffer(Buffer.from("foobarbuzz")); - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, mockData); - expect(await sdkStream.transformToByteArray()).toEqual(expected); - }); - - it("should fail any subsequent tranform calls", async () => { - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("abc")]); - expect(await sdkStream.transformToByteArray()).toEqual(byteArrayFromBuffer(Buffer.from("abc"))); - await expectAllTransformsToFail(sdkStream); - }); - }); - - describe("transformToString", () => { - const toStringMock = jest.fn(); - beforeAll(() => { - jest.resetAllMocks(); - }); - - it("should transform the stream to string with utf-8 encoding by default", async () => { - (fromArrayBuffer as jest.Mock).mockImplementation(jest.requireActual("@smithy/util-buffer-from").fromArrayBuffer); - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("foo")]); - const transformed = await sdkStream.transformToString(); - expect(transformed).toEqual("foo"); - }); - - it.each([undefined, "utf-8", "ascii", "base64", "latin1", "binary"])( - "should transform the stream to string with %s encoding", - async (encoding) => { - (fromArrayBuffer as jest.Mock).mockReturnValue({ toString: toStringMock }); - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("foo")]); - await sdkStream.transformToString(encoding); - expect(toStringMock).toBeCalledWith(encoding); - } - ); - - it.each(["ibm866", "iso-8859-2", "koi8-r", "macintosh", "windows-874", "gbk", "gb18030", "euc-jp"])( - "should transform the stream to string with TextDecoder config %s", - async (encoding) => { - jest.spyOn(util, "TextDecoder").mockImplementation( - () => - ({ - decode: jest.fn(), - }) as any - ); - (fromArrayBuffer as jest.Mock).mockReturnValue({ toString: toStringMock }); - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("foo")]); - await sdkStream.transformToString(encoding as BufferEncoding); - expect(util.TextDecoder).toBeCalledWith(encoding); - } - ); - - it("should fail any subsequent tranform calls", async () => { - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("foo")]); - await sdkStream.transformToString(); - await expectAllTransformsToFail(sdkStream); - }); - }); - - describe("transformToWebStream", () => { - it("should throw if any event listener is attached on the underlying stream", async () => { - passThrough.on("data", console.log); - const sdkStream = sdkStreamMixin(passThrough); - try { - sdkStream.transformToWebStream(); - fail(new Error("expect web stream transformation to fail")); - } catch (error) { - expect(error.message).toContain("The stream has been consumed by other callbacks"); - } - }); - - describe("when Readable.toWeb() is not supported", () => { - // @ts-expect-error - const originalToWebImpl = Readable.toWeb; - beforeAll(() => { - // @ts-expect-error - Readable.toWeb = undefined; - }); - afterAll(() => { - // @ts-expect-error - Readable.toWeb = originalToWebImpl; - }); - - it("should throw", async () => { - const sdkStream = sdkStreamMixin(passThrough); - try { - sdkStream.transformToWebStream(); - fail(new Error("expect web stream transformation to fail")); - } catch (error) { - expect(error.message).toContain("Readable.toWeb() is not supported"); - } - }); - }); - - describe("when Readable.toWeb() is supported", () => { - // @ts-expect-error - const originalToWebImpl = Readable.toWeb; - beforeAll(() => { - // @ts-expect-error - Readable.toWeb = jest.fn().mockReturnValue("A web stream"); - }); - - afterAll(() => { - // @ts-expect-error - Readable.toWeb = originalToWebImpl; - }); - - it("should tranform Node stream to web stream", async () => { - const sdkStream = sdkStreamMixin(passThrough); - sdkStream.transformToWebStream(); - // @ts-expect-error - expect(Readable.toWeb).toBeCalled(); - }); - - it("should fail any subsequent tranform calls", async () => { - const sdkStream = sdkStreamMixin(passThrough); - await writeDataToStream(passThrough, [Buffer.from("foo")]); - await sdkStream.transformToWebStream(); - await expectAllTransformsToFail(sdkStream); - }); - }); - }); -}); diff --git a/packages/util-stream/jest.config.integ.js b/packages/util-stream/jest.config.integ.js deleted file mode 100644 index 58cf5258099..00000000000 --- a/packages/util-stream/jest.config.integ.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testMatch: ["**/*.integ.spec.ts"], -}; diff --git a/packages/util-stream/jest.config.js b/packages/util-stream/jest.config.js deleted file mode 100644 index fa2ccdd2f97..00000000000 --- a/packages/util-stream/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testPathIgnorePatterns: ["(.*).browser.spec.js"], -}; diff --git a/packages/util-stream/karma.conf.js b/packages/util-stream/karma.conf.js deleted file mode 100644 index b2ae368b568..00000000000 --- a/packages/util-stream/karma.conf.js +++ /dev/null @@ -1,34 +0,0 @@ -// Set up binary for Chromium browser in CHROME_BIN environment variable before running the test - -module.exports = function (config) { - config.set({ - frameworks: ["jasmine", "karma-typescript"], - files: [ - "src/checksum/createChecksumStream.browser.spec.ts", - "src/checksum/createChecksumStream.browser.ts", - "src/checksum/ChecksumStream.browser.ts", - "src/getAwsChunkedEncodingStream.browser.spec.ts", - "src/getAwsChunkedEncodingStream.browser.ts", - "src/headStream.browser.ts", - "src/stream-type-check.ts", - ], - exclude: ["**/*.d.ts"], - preprocessors: { - "**/*.ts": "karma-typescript", - }, - reporters: ["progress", "karma-typescript"], - browsers: ["ChromeHeadlessNoSandbox"], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: "ChromeHeadless", - flags: ["--no-sandbox"], - }, - }, - karmaTypescriptConfig: { - bundlerOptions: { - addNodeGlobals: true, - }, - }, - singleRun: true, - }); -}; diff --git a/packages/util-stream/package.json b/packages/util-stream/package.json index 89bdfde7b4c..5b893f3f565 100644 --- a/packages/util-stream/package.json +++ b/packages/util-stream/package.json @@ -12,8 +12,12 @@ "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", "extract:docs": "api-extractor run --local", - "test": "yarn g:jest && yarn g:karma start karma.conf.js", - "test:integration": "yarn g:jest --config jest.config.integ.js" + "test": "yarn g:vitest run && yarn test:browser", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:watch": "yarn g:vitest watch", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts", + "test:browser": "yarn g:vitest run -c vitest.config.browser.ts", + "test:browser:watch": "yarn g:vitest watch -c vitest.config.browser.ts" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-stream/src/blob/Uint8ArrayBlobAdapter.spec.ts b/packages/util-stream/src/blob/Uint8ArrayBlobAdapter.spec.ts index d8f071c1965..ff0f7907d01 100644 --- a/packages/util-stream/src/blob/Uint8ArrayBlobAdapter.spec.ts +++ b/packages/util-stream/src/blob/Uint8ArrayBlobAdapter.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { Uint8ArrayBlobAdapter } from "./Uint8ArrayBlobAdapter"; describe(Uint8ArrayBlobAdapter.name, () => { diff --git a/packages/util-stream/src/checksum/createChecksumStream.browser.spec.ts b/packages/util-stream/src/checksum/createChecksumStream.browser.spec.ts index 0f90a5eb2f0..13263d96565 100644 --- a/packages/util-stream/src/checksum/createChecksumStream.browser.spec.ts +++ b/packages/util-stream/src/checksum/createChecksumStream.browser.spec.ts @@ -1,89 +1,93 @@ import { Checksum } from "@smithy/types"; import { toBase64 } from "@smithy/util-base64"; import { toUtf8 } from "@smithy/util-utf8"; +import { describe, expect, test as it } from "vitest"; import { headStream } from "../headStream.browser"; import { ChecksumStream as ChecksumStreamWeb } from "./ChecksumStream.browser"; import { createChecksumStream } from "./createChecksumStream.browser"; -describe("Checksum streams", () => { - /** - * Hash "algorithm" that appends all data together. - */ - class Appender implements Checksum { - public hash = ""; - async digest(): Promise { - return Buffer.from(this.hash); - } - reset(): void { - throw new Error("Function not implemented."); - } - update(chunk: Uint8Array): void { - this.hash += toUtf8(chunk); +(typeof ReadableStream === "function" && process.version >= "v18" ? describe : describe.skip)( + "Checksum streams", + () => { + /** + * Hash "algorithm" that appends all data together. + */ + class Appender implements Checksum { + public hash = ""; + async digest(): Promise { + return Buffer.from(this.hash); + } + reset(): void { + throw new Error("Function not implemented."); + } + update(chunk: Uint8Array): void { + this.hash += toUtf8(chunk); + } } - } - const canonicalData = new Uint8Array("abcdefghijklmnopqrstuvwxyz".split("").map((_) => _.charCodeAt(0))); + const canonicalData = new Uint8Array("abcdefghijklmnopqrstuvwxyz".split("").map((_) => _.charCodeAt(0))); - const canonicalUtf8 = toUtf8(canonicalData); - const canonicalBase64 = toBase64(canonicalUtf8); - - describe(createChecksumStream.name + " webstreams API", () => { - if (typeof ReadableStream !== "function") { - // test not applicable to Node.js 16. - return; - } + const canonicalUtf8 = toUtf8(canonicalData); + const canonicalBase64 = toBase64(canonicalUtf8); - const makeStream = () => { - return new ReadableStream({ - start(controller) { - canonicalData.forEach((byte) => { - controller.enqueue(new Uint8Array([byte])); - }); - controller.close(); - }, - }); - }; + describe(createChecksumStream.name + " webstreams API", () => { + if (typeof ReadableStream !== "function") { + // test not applicable to Node.js 16. + return; + } - it("should extend a ReadableStream", async () => { - const stream = makeStream(); - const checksumStream = createChecksumStream({ - expectedChecksum: canonicalBase64, - checksum: new Appender(), - checksumSourceLocation: "my-header", - source: stream, - }); + const makeStream = () => { + return new ReadableStream({ + start(controller) { + canonicalData.forEach((byte) => { + controller.enqueue(new Uint8Array([byte])); + }); + controller.close(); + }, + }); + }; - expect(checksumStream).toBeInstanceOf(ReadableStream); - expect(checksumStream).toBeInstanceOf(ChecksumStreamWeb); + it("should extend a ReadableStream", async () => { + const stream = makeStream(); + const checksumStream = createChecksumStream({ + expectedChecksum: canonicalBase64, + checksum: new Appender(), + checksumSourceLocation: "my-header", + source: stream, + }); - const collected = toUtf8(await headStream(checksumStream, Infinity)); - expect(collected).toEqual(canonicalUtf8); - expect(stream.locked).toEqual(true); + expect(checksumStream).toBeInstanceOf(ReadableStream); + expect(checksumStream).toBeInstanceOf(ChecksumStreamWeb); - // expectation is that it is resolved. - expect(await checksumStream.getReader().closed); - }); + const collected = toUtf8(await headStream(checksumStream, Infinity)); + expect(collected).toEqual(canonicalUtf8); + expect(stream.locked).toEqual(true); - it("should throw during stream read if the checksum does not match", async () => { - const stream = makeStream(); - const checksumStream = createChecksumStream({ - expectedChecksum: "different-expected-checksum", - checksum: new Appender(), - checksumSourceLocation: "my-header", - source: stream, + // expectation is that it is resolved. + expect(await checksumStream.getReader().closed); }); - try { - toUtf8(await headStream(checksumStream, Infinity)); - throw new Error("stream was read successfully"); - } catch (e: unknown) { - expect(String(e)).toEqual( - `Error: Checksum mismatch: expected "different-expected-checksum" but` + - ` received "${canonicalBase64}"` + - ` in response header "my-header".` - ); - } + it("should throw during stream read if the checksum does not match", async () => { + const stream = makeStream(); + const checksumStream = createChecksumStream({ + expectedChecksum: "different-expected-checksum", + checksum: new Appender(), + checksumSourceLocation: "my-header", + source: stream, + }); + + try { + toUtf8(await headStream(checksumStream, Infinity)); + throw new Error("stream was read successfully"); + } catch (e: unknown) { + expect(String(e)).toEqual( + `Error: Checksum mismatch: expected "different-expected-checksum" but` + + ` received "${canonicalBase64}"` + + ` in response header "my-header".` + ); + } + }); }); - }); -}); + } +); diff --git a/packages/util-stream/src/checksum/createChecksumStream.spec.ts b/packages/util-stream/src/checksum/createChecksumStream.spec.ts index 8abf019b592..ad34a1d706a 100644 --- a/packages/util-stream/src/checksum/createChecksumStream.spec.ts +++ b/packages/util-stream/src/checksum/createChecksumStream.spec.ts @@ -2,6 +2,7 @@ import { Checksum } from "@smithy/types"; import { toBase64 } from "@smithy/util-base64"; import { toUtf8 } from "@smithy/util-utf8"; import { Readable } from "stream"; +import { describe, expect, test as it } from "vitest"; import { headStream } from "../headStream"; import { ChecksumStream } from "./ChecksumStream"; @@ -77,6 +78,7 @@ describe("Checksum streams", () => { describe(createChecksumStream.name + " webstreams API", () => { if (typeof ReadableStream !== "function") { + it.skip("Skipped when ReadableStream is not globally available.", () => {}); // test not applicable to Node.js 16. return; } diff --git a/packages/util-stream/src/getAwsChunkedEncodingStream.browser.spec.ts b/packages/util-stream/src/getAwsChunkedEncodingStream.browser.spec.ts index f6389b97a6b..80c572ea5f4 100644 --- a/packages/util-stream/src/getAwsChunkedEncodingStream.browser.spec.ts +++ b/packages/util-stream/src/getAwsChunkedEncodingStream.browser.spec.ts @@ -1,4 +1,5 @@ -// @jest-environment jsdom +import { describe, expect, test as it } from "vitest"; + import { getAwsChunkedEncodingStream } from "./getAwsChunkedEncodingStream.browser"; describe(getAwsChunkedEncodingStream.name, () => { diff --git a/packages/util-stream/src/getAwsChunkedEncodingStream.spec.ts b/packages/util-stream/src/getAwsChunkedEncodingStream.spec.ts index d593a5db742..7c6ef075114 100644 --- a/packages/util-stream/src/getAwsChunkedEncodingStream.spec.ts +++ b/packages/util-stream/src/getAwsChunkedEncodingStream.spec.ts @@ -1,13 +1,14 @@ import { Readable } from "stream"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { getAwsChunkedEncodingStream } from "./getAwsChunkedEncodingStream"; describe(getAwsChunkedEncodingStream.name, () => { - const mockBase64Encoder = jest.fn(); - const mockBodyLengthChecker = jest.fn(); - const mockChecksumAlgorithmFn = jest.fn(); + const mockBase64Encoder = vi.fn(); + const mockBodyLengthChecker = vi.fn(); + const mockChecksumAlgorithmFn = vi.fn(); const mockChecksumLocationName = "mockChecksumLocationName"; - const mockStreamHasher = jest.fn(); + const mockStreamHasher = vi.fn(); const mockOptions = { base64Encoder: mockBase64Encoder, @@ -42,12 +43,14 @@ describe(getAwsChunkedEncodingStream.name, () => { mockStreamChunks.forEach((chunk, index) => { expect(mockBodyLengthChecker).toHaveBeenNthCalledWith(index + 1, Buffer.from(chunk)); }); - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("skips checksum computation", () => { - const validateStreamWithoutChecksum = (awsChunkedEncodingStream: Readable, done: Function) => { + const validateStreamWithoutChecksum = async (awsChunkedEncodingStream: Readable) => { let buffer = ""; + let resolve: Function; + const promise = new Promise((r) => (resolve = r)); awsChunkedEncodingStream.on("data", (data) => { buffer += data.toString(); }); @@ -60,34 +63,36 @@ Hello\r World\r 0\r `); - done(); + resolve(); }); + await promise; }; - it("if none of the required options are passed", (done) => { + it("if none of the required options are passed", async () => { const readableStream = getMockReadableStream(); const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, { bodyLengthChecker: mockBodyLengthChecker, }); - validateStreamWithoutChecksum(awsChunkedEncodingStream, done); + await validateStreamWithoutChecksum(awsChunkedEncodingStream); }); ["base64Encoder", "checksumAlgorithmFn", "checksumLocationName", "streamHasher"].forEach((optionToRemove) => { - it(`if option '${optionToRemove}' is not passed`, (done) => { + it(`if option '${optionToRemove}' is not passed`, async () => { const readableStream = getMockReadableStream(); const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, { ...mockOptions, [optionToRemove]: undefined, }); - validateStreamWithoutChecksum(awsChunkedEncodingStream, done); + await validateStreamWithoutChecksum(awsChunkedEncodingStream); }); }); }); - it("computes checksum and adds it to the end event", (done) => { + it("computes checksum and adds it to the end event", async () => { const readableStream = getMockReadableStream(); const awsChunkedEncodingStream = getAwsChunkedEncodingStream(readableStream, mockOptions); - + let resolve: Function; + const promise = new Promise((r) => (resolve = r)); let buffer = ""; awsChunkedEncodingStream.on("data", (data) => { buffer += data.toString(); @@ -103,7 +108,8 @@ World\r mockChecksumLocationName:mockChecksum\r \r `); - done(); + resolve(); }); + await promise; }); }); diff --git a/packages/util-stream/src/headStream.spec.ts b/packages/util-stream/src/headStream.spec.ts index 18294f9bf7a..4324db8411d 100644 --- a/packages/util-stream/src/headStream.spec.ts +++ b/packages/util-stream/src/headStream.spec.ts @@ -1,4 +1,5 @@ import { Readable } from "stream"; +import { describe, expect, test as it } from "vitest"; import { headStream } from "./headStream"; import { headStream as headWebStream } from "./headStream.browser"; diff --git a/packages/util-stream/src/sdk-stream-mixin.browser.spec.ts b/packages/util-stream/src/sdk-stream-mixin.browser.spec.ts index f3d7b896f01..1f157f22b06 100644 --- a/packages/util-stream/src/sdk-stream-mixin.browser.spec.ts +++ b/packages/util-stream/src/sdk-stream-mixin.browser.spec.ts @@ -1,19 +1,19 @@ -// @jest-environment jsdom import { streamCollector } from "@smithy/fetch-http-handler"; import { SdkStreamMixin } from "@smithy/types"; import { toBase64 } from "@smithy/util-base64"; import { toHex } from "@smithy/util-hex-encoding"; import { toUtf8 } from "@smithy/util-utf8"; +import { afterEach, beforeAll, beforeEach, describe, expect, test as it, vi } from "vitest"; import { sdkStreamMixin } from "./sdk-stream-mixin.browser"; -jest.mock("@smithy/fetch-http-handler"); -jest.mock("@smithy/util-base64"); -jest.mock("@smithy/util-hex-encoding"); -jest.mock("@smithy/util-utf8"); +vi.mock("@smithy/fetch-http-handler"); +vi.mock("@smithy/util-base64"); +vi.mock("@smithy/util-hex-encoding"); +vi.mock("@smithy/util-utf8"); const mockStreamCollectorReturn = Uint8Array.from([117, 112, 113]); -(streamCollector as jest.Mock).mockReturnValue(mockStreamCollectorReturn); +vi.mocked(streamCollector).mockReturnValue(Promise.resolve(mockStreamCollectorReturn)); describe(sdkStreamMixin.name, () => { const expectAllTransformsToFail = async (sdkStream: SdkStreamMixin) => { @@ -33,7 +33,7 @@ describe(sdkStreamMixin.name, () => { }; let originalReadableStreamCtr = global.ReadableStream; - const mockReadableStream = jest.fn(); + const mockReadableStream = vi.fn(); class ReadableStream { constructor() { mockReadableStream(); @@ -48,7 +48,7 @@ describe(sdkStreamMixin.name, () => { beforeEach(() => { originalReadableStreamCtr = global.ReadableStream; - jest.clearAllMocks(); + vi.clearAllMocks(); payloadStream = new ReadableStream(); }); @@ -58,13 +58,15 @@ describe(sdkStreamMixin.name, () => { it("should throw if input stream is not a Blob or Web Stream instance", () => { const originalBlobCtr = global.Blob; + // @ts-expect-error global.Blob = undefined; + // @ts-expect-error global.ReadableStream = undefined; try { sdkStreamMixin({}); fail("expect unexpected stream to fail"); } catch (e) { - expect(e.message).toContain("unexpected stream implementation"); + expect(e.message).toContain("Unexpected stream implementation"); global.Blob = originalBlobCtr; } }); @@ -73,7 +75,7 @@ describe(sdkStreamMixin.name, () => { it("should transform binary stream to byte array", async () => { const sdkStream = sdkStreamMixin(payloadStream); const byteArray = await sdkStream.transformToByteArray(); - expect(streamCollector as jest.Mock).toBeCalledWith(payloadStream); + expect(vi.mocked(streamCollector)).toBeCalledWith(payloadStream); expect(byteArray).toEqual(mockStreamCollectorReturn); }); @@ -86,14 +88,14 @@ describe(sdkStreamMixin.name, () => { describe("transformToString", () => { let originalTextDecoder = global.TextDecoder; - const mockDecode = jest.fn(); - global.TextDecoder = jest.fn().mockImplementation(function () { + const mockDecode = vi.fn(); + global.TextDecoder = vi.fn().mockImplementation(function () { return { decode: mockDecode }; }); beforeEach(() => { originalTextDecoder = global.TextDecoder; - jest.clearAllMocks(); + vi.clearAllMocks(); }); afterEach(() => { @@ -108,7 +110,7 @@ describe(sdkStreamMixin.name, () => { ["hex", toHex], ])("should transform to string with %s encoding", async (encoding, encodingFn) => { const mockEncodedStringValue = `a string with ${encoding} encoding`; - (encodingFn as jest.Mock).mockReturnValueOnce(mockEncodedStringValue); + vi.mocked(encodingFn).mockReturnValueOnce(mockEncodedStringValue); const sdkStream = sdkStreamMixin(payloadStream); const str = await sdkStream.transformToString(encoding); expect(streamCollector).toBeCalled(); @@ -126,6 +128,7 @@ describe(sdkStreamMixin.name, () => { }); it("should throw if TextDecoder is not available", async () => { + // @ts-expect-error global.TextDecoder = null; const utfLabel = "windows-1251"; const sdkStream = sdkStreamMixin(payloadStream); @@ -162,8 +165,8 @@ describe(sdkStreamMixin.name, () => { describe("transformToWebStream with Blob payload", () => { let originalBlobCtr = global.Blob; - const mockBlob = jest.fn(); - const mockBlobStream = jest.fn(); + const mockBlob = vi.fn(); + const mockBlobStream = vi.fn(); class Blob { constructor() { mockBlob(); @@ -176,9 +179,10 @@ describe(sdkStreamMixin.name, () => { global.Blob = Blob as any; beforeEach(() => { + // @ts-expect-error global.ReadableStream = undefined; originalBlobCtr = global.Blob; - jest.clearAllMocks(); + vi.clearAllMocks(); }); afterEach(() => { diff --git a/packages/util-stream/src/sdk-stream-mixin.spec.ts b/packages/util-stream/src/sdk-stream-mixin.spec.ts index f5900baf630..d2d705d9c11 100644 --- a/packages/util-stream/src/sdk-stream-mixin.spec.ts +++ b/packages/util-stream/src/sdk-stream-mixin.spec.ts @@ -1,11 +1,11 @@ import { SdkStreamMixin } from "@smithy/types"; import { fromArrayBuffer } from "@smithy/util-buffer-from"; import { PassThrough, Readable, Writable } from "stream"; -import util from "util"; +import { afterAll, beforeAll, beforeEach, describe, expect, test as it, vi } from "vitest"; import { sdkStreamMixin } from "./sdk-stream-mixin"; -jest.mock("@smithy/util-buffer-from"); +vi.mock("@smithy/util-buffer-from"); describe(sdkStreamMixin.name, () => { const writeDataToStream = (stream: Writable, data: Array): Promise => @@ -82,13 +82,15 @@ describe(sdkStreamMixin.name, () => { }); describe("transformToString", () => { - const toStringMock = jest.fn(); + const toStringMock = vi.fn(); beforeAll(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it("should transform the stream to string with utf-8 encoding by default", async () => { - (fromArrayBuffer as jest.Mock).mockImplementation(jest.requireActual("@smithy/util-buffer-from").fromArrayBuffer); + vi.mocked(fromArrayBuffer).mockImplementation( + ((await vi.importActual("@smithy/util-buffer-from")) as any).fromArrayBuffer + ); const sdkStream = sdkStreamMixin(passThrough); await writeDataToStream(passThrough, [Buffer.from("foo")]); const transformed = await sdkStream.transformToString(); @@ -98,7 +100,7 @@ describe(sdkStreamMixin.name, () => { it.each([undefined, "utf-8", "ascii", "base64", "latin1", "binary"])( "should transform the stream to string with %s encoding", async (encoding) => { - (fromArrayBuffer as jest.Mock).mockReturnValue({ toString: toStringMock }); + vi.mocked(fromArrayBuffer).mockReturnValue({ toString: toStringMock } as any); const sdkStream = sdkStreamMixin(passThrough); await writeDataToStream(passThrough, [Buffer.from("foo")]); await sdkStream.transformToString(encoding); @@ -109,17 +111,17 @@ describe(sdkStreamMixin.name, () => { it.each(["ibm866", "iso-8859-2", "koi8-r", "macintosh", "windows-874", "gbk", "gb18030", "euc-jp"])( "should transform the stream to string with TextDecoder config %s", async (encoding) => { - jest.spyOn(util, "TextDecoder").mockImplementation( + vi.spyOn(global, "TextDecoder").mockImplementation( () => ({ - decode: jest.fn(), + decode: vi.fn(), }) as any ); - (fromArrayBuffer as jest.Mock).mockReturnValue({ toString: toStringMock }); + vi.mocked(fromArrayBuffer).mockReturnValue({ toString: toStringMock } as any); const sdkStream = sdkStreamMixin(passThrough); await writeDataToStream(passThrough, [Buffer.from("foo")]); await sdkStream.transformToString(encoding as BufferEncoding); - expect(util.TextDecoder).toBeCalledWith(encoding); + expect(TextDecoder).toBeCalledWith(encoding); } ); @@ -171,7 +173,7 @@ describe(sdkStreamMixin.name, () => { const originalToWebImpl = Readable.toWeb; beforeAll(() => { // @ts-expect-error - Readable.toWeb = jest.fn().mockReturnValue("A web stream"); + Readable.toWeb = vi.fn().mockReturnValue("A web stream"); }); afterAll(() => { diff --git a/packages/util-stream/src/sdk-stream-mixin.ts b/packages/util-stream/src/sdk-stream-mixin.ts index 99adb59c605..3c716fb9fe2 100644 --- a/packages/util-stream/src/sdk-stream-mixin.ts +++ b/packages/util-stream/src/sdk-stream-mixin.ts @@ -2,7 +2,6 @@ import { streamCollector } from "@smithy/node-http-handler"; import { SdkStream, SdkStreamMixin } from "@smithy/types"; import { fromArrayBuffer } from "@smithy/util-buffer-from"; import { Readable } from "stream"; -import { TextDecoder } from "util"; import { sdkStreamMixin as sdkStreamMixinReadableStream } from "./sdk-stream-mixin.browser"; diff --git a/packages/util-stream/src/splitStream.spec.ts b/packages/util-stream/src/splitStream.spec.ts index d5e3d7b7e8e..763b522b0dd 100644 --- a/packages/util-stream/src/splitStream.spec.ts +++ b/packages/util-stream/src/splitStream.spec.ts @@ -1,6 +1,7 @@ import { streamCollector as webStreamCollector } from "@smithy/fetch-http-handler"; import { streamCollector } from "@smithy/node-http-handler"; import { Readable } from "stream"; +import { describe, expect, test as it } from "vitest"; import { splitStream } from "./splitStream"; import { splitStream as splitWebStream } from "./splitStream.browser"; diff --git a/packages/util-stream/src/util-stream.integ.spec.ts b/packages/util-stream/src/util-stream.integ.spec.ts index 6d68c16e27e..09591c004f0 100644 --- a/packages/util-stream/src/util-stream.integ.spec.ts +++ b/packages/util-stream/src/util-stream.integ.spec.ts @@ -1,11 +1,13 @@ import { HttpHandler, HttpResponse } from "@smithy/protocol-http"; import { HttpRequest as IHttpRequest } from "@smithy/types"; import { Uint8ArrayBlobAdapter } from "@smithy/util-stream"; -import { requireRequestsFrom } from "@smithy/util-test"; import { fromUtf8 } from "@smithy/util-utf8"; import { Readable } from "stream"; +import { describe, expect, test as it } from "vitest"; import { Weather } from "weather"; +import { requireRequestsFrom } from "../../../private/util-test/src/index"; + describe("util-stream", () => { describe(Weather.name, () => { it("should be uniform between string and Uint8Array payloads", async () => { diff --git a/packages/util-stream/vitest.config.browser.ts b/packages/util-stream/vitest.config.browser.ts new file mode 100644 index 00000000000..9c10f139e48 --- /dev/null +++ b/packages/util-stream/vitest.config.browser.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e}.spec.ts"], + include: ["**/*.browser.spec.ts"], + environment: "happy-dom", + }, +}); diff --git a/packages/util-stream/vitest.config.integ.ts b/packages/util-stream/vitest.config.integ.ts new file mode 100644 index 00000000000..5802db1ac64 --- /dev/null +++ b/packages/util-stream/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-stream/vitest.config.ts b/packages/util-stream/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-stream/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-uri-escape/jest.config.js b/packages/util-uri-escape/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-uri-escape/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-uri-escape/package.json b/packages/util-uri-escape/package.json index 3416ad743b9..a7a4e91f192 100644 --- a/packages/util-uri-escape/package.json +++ b/packages/util-uri-escape/package.json @@ -11,7 +11,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-uri-escape/src/escape-uri-path.spec.ts b/packages/util-uri-escape/src/escape-uri-path.spec.ts index 4805bc4d2ca..08aa6ca47c0 100644 --- a/packages/util-uri-escape/src/escape-uri-path.spec.ts +++ b/packages/util-uri-escape/src/escape-uri-path.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { escapeUriPath } from "./escape-uri-path"; describe("escapeUriPath", () => { diff --git a/packages/util-uri-escape/src/escape-uri.spec.ts b/packages/util-uri-escape/src/escape-uri.spec.ts index c256c35601a..f816250f40d 100644 --- a/packages/util-uri-escape/src/escape-uri.spec.ts +++ b/packages/util-uri-escape/src/escape-uri.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { escapeUri } from "./escape-uri"; describe("escapeUri", () => { diff --git a/packages/util-uri-escape/vitest.config.ts b/packages/util-uri-escape/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-uri-escape/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-utf8/jest.config.js b/packages/util-utf8/jest.config.js deleted file mode 100644 index 95d8863b22a..00000000000 --- a/packages/util-utf8/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, - testMatch: ["**/*.spec.ts"], -}; diff --git a/packages/util-utf8/package.json b/packages/util-utf8/package.json index 26aa47378d6..deda618bf7a 100644 --- a/packages/util-utf8/package.json +++ b/packages/util-utf8/package.json @@ -14,7 +14,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-utf8/src/fromUtf8.browser.spec.ts b/packages/util-utf8/src/fromUtf8.browser.spec.ts index 4d97df92610..0067c1f1a44 100644 --- a/packages/util-utf8/src/fromUtf8.browser.spec.ts +++ b/packages/util-utf8/src/fromUtf8.browser.spec.ts @@ -1,6 +1,5 @@ -/** - * @jest-environment jsdom - */ +import { describe, expect, test as it, vi } from "vitest"; + import { fromUtf8 } from "./fromUtf8.browser"; declare const global: any; @@ -8,8 +7,8 @@ declare const global: any; describe("fromUtf8", () => { it("should use the Encoding API", () => { const expected = new Uint8Array(0); - const encode = jest.fn().mockReturnValue(expected); - (global as any).TextEncoder = jest.fn(() => ({ encode })); + const encode = vi.fn().mockReturnValue(expected); + (global as any).TextEncoder = vi.fn(() => ({ encode })); expect(fromUtf8("ABC")).toBe(expected); }); diff --git a/packages/util-utf8/src/fromUtf8.spec.ts b/packages/util-utf8/src/fromUtf8.spec.ts index 5cc02b88e9b..53be64982c6 100644 --- a/packages/util-utf8/src/fromUtf8.spec.ts +++ b/packages/util-utf8/src/fromUtf8.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { fromUtf8 } from "./fromUtf8"; const utf8StringsToByteArrays: Record = { diff --git a/packages/util-utf8/src/toUint8Array.spec.ts b/packages/util-utf8/src/toUint8Array.spec.ts index cff395d2759..1fbf7e3aab7 100644 --- a/packages/util-utf8/src/toUint8Array.spec.ts +++ b/packages/util-utf8/src/toUint8Array.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { toUint8Array } from "./toUint8Array"; describe("toUint8Array", () => { diff --git a/packages/util-utf8/src/toUtf8.browser.spec.ts b/packages/util-utf8/src/toUtf8.browser.spec.ts index c5d82b0f5b4..9d8b20fa870 100644 --- a/packages/util-utf8/src/toUtf8.browser.spec.ts +++ b/packages/util-utf8/src/toUtf8.browser.spec.ts @@ -1,7 +1,5 @@ -/** - * @jest-environment jsdom - */ import type { Encoder } from "@smithy/types"; +import { describe, expect, test as it, vi } from "vitest"; import { toUtf8 } from "./toUtf8.browser"; @@ -10,8 +8,8 @@ declare const global: any; describe("toUtf8", () => { it("should use the Encoding API", () => { const expected = "ABC"; - const decode = jest.fn().mockReturnValue(expected); - (global as any).TextDecoder = jest.fn(() => ({ decode })); + const decode = vi.fn().mockReturnValue(expected); + (global as any).TextDecoder = vi.fn(() => ({ decode })); expect(toUtf8(new Uint8Array(0))).toBe(expected); }); diff --git a/packages/util-utf8/src/toUtf8.spec.ts b/packages/util-utf8/src/toUtf8.spec.ts index 2e315834f5e..325268de31e 100644 --- a/packages/util-utf8/src/toUtf8.spec.ts +++ b/packages/util-utf8/src/toUtf8.spec.ts @@ -1,4 +1,5 @@ import type { Encoder } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { toUtf8 } from "./toUtf8"; diff --git a/packages/util-utf8/vitest.config.ts b/packages/util-utf8/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-utf8/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/packages/util-waiter/jest.config.js b/packages/util-waiter/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/packages/util-waiter/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-waiter/package.json b/packages/util-waiter/package.json index 4eca272a3b2..863168ff112 100644 --- a/packages/util-waiter/package.json +++ b/packages/util-waiter/package.json @@ -17,7 +17,8 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", "lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"", "format": "prettier --config ../../prettier.config.js --ignore-path ../.prettierignore --write \"**/*.{ts,md,json}\"", - "test": "yarn g:jest" + "test": "yarn g:vitest run", + "test:watch": "yarn g:vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-waiter/src/createWaiter.spec.ts b/packages/util-waiter/src/createWaiter.spec.ts index 3061d99673c..60a5cebd38c 100644 --- a/packages/util-waiter/src/createWaiter.spec.ts +++ b/packages/util-waiter/src/createWaiter.spec.ts @@ -1,21 +1,21 @@ import { AbortController } from "@smithy/abort-controller"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { WaiterOptions, WaiterState } from "./waiter"; -const mockValidate = jest.fn(); -jest.mock("./utils/validate", () => ({ - validateWaiterOptions: mockValidate, +vi.mock("./utils/validate", () => ({ + validateWaiterOptions: vi.fn(), })); import { createWaiter } from "./createWaiter"; describe("createWaiter", () => { beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); const minimalWaiterConfig = { @@ -41,7 +41,7 @@ describe("createWaiter", () => { it("should abort when abortController is signalled", async () => { const abortController = new AbortController(); - const mockAcceptorChecks = jest.fn().mockResolvedValue(retryState); + const mockAcceptorChecks = vi.fn().mockResolvedValue(retryState); const statusPromise = createWaiter( { ...minimalWaiterConfig, @@ -51,13 +51,13 @@ describe("createWaiter", () => { input, mockAcceptorChecks ); - jest.advanceTimersByTime(10 * 1000); + vi.advanceTimersByTime(10 * 1000); abortController.abort(); // Abort before maxWaitTime(20s); expect(await statusPromise).toEqual(abortedState); }); it("should success when acceptor checker returns seccess", async () => { - const mockAcceptorChecks = jest.fn().mockResolvedValue(successState); + const mockAcceptorChecks = vi.fn().mockResolvedValue(successState); const statusPromise = createWaiter( { ...minimalWaiterConfig, @@ -66,12 +66,12 @@ describe("createWaiter", () => { input, mockAcceptorChecks ); - jest.advanceTimersByTime(minimalWaiterConfig.minDelay * 1000); + vi.advanceTimersByTime(minimalWaiterConfig.minDelay * 1000); expect(await statusPromise).toEqual(successState); }); it("should fail when acceptor checker returns failure", async () => { - const mockAcceptorChecks = jest.fn().mockResolvedValue(failureState); + const mockAcceptorChecks = vi.fn().mockResolvedValue(failureState); const statusPromise = createWaiter( { ...minimalWaiterConfig, @@ -80,7 +80,7 @@ describe("createWaiter", () => { input, mockAcceptorChecks ); - jest.advanceTimersByTime(minimalWaiterConfig.minDelay * 1000); + vi.advanceTimersByTime(minimalWaiterConfig.minDelay * 1000); expect(await statusPromise).toEqual(failureState); }); }); diff --git a/packages/util-waiter/src/index.spec.ts b/packages/util-waiter/src/index.spec.ts index 3bf2ab465c4..22f7624a4e0 100644 --- a/packages/util-waiter/src/index.spec.ts +++ b/packages/util-waiter/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import * as exported from "./index"; describe("Waiter util module exports", () => { diff --git a/packages/util-waiter/src/poller.spec.ts b/packages/util-waiter/src/poller.spec.ts index 8a93e5083fd..a5a5f78d6a7 100644 --- a/packages/util-waiter/src/poller.spec.ts +++ b/packages/util-waiter/src/poller.spec.ts @@ -1,10 +1,11 @@ import { AbortController } from "@smithy/abort-controller"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { runPolling } from "./poller"; import { sleep } from "./utils/sleep"; import { WaiterOptions, WaiterState } from "./waiter"; -jest.mock("./utils/sleep"); +vi.mock("./utils/sleep"); describe(runPolling.name, () => { const config = { @@ -40,17 +41,17 @@ describe(runPolling.name, () => { let mockAcceptorChecks; beforeEach(() => { - (sleep as jest.Mock).mockResolvedValueOnce(""); - jest.spyOn(global.Math, "random").mockReturnValue(0.5); + vi.mocked(sleep).mockResolvedValueOnce(""); + vi.spyOn(global.Math, "random").mockReturnValue(0.5); }); afterEach(() => { - jest.clearAllMocks(); - jest.spyOn(global.Math, "random").mockRestore(); + vi.clearAllMocks(); + vi.spyOn(global.Math, "random").mockRestore(); }); it("should returns state and reason in case of failure", async () => { - mockAcceptorChecks = jest.fn().mockResolvedValueOnce(failureState); + mockAcceptorChecks = vi.fn().mockResolvedValueOnce(failureState); await expect(runPolling(config, input, mockAcceptorChecks)).resolves.toStrictEqual(failureState); expect(mockAcceptorChecks).toHaveBeenCalled(); @@ -60,7 +61,7 @@ describe(runPolling.name, () => { }); it("returns state and reason in case of success", async () => { - mockAcceptorChecks = jest.fn().mockResolvedValueOnce(successState); + mockAcceptorChecks = vi.fn().mockResolvedValueOnce(successState); await expect(runPolling(config, input, mockAcceptorChecks)).resolves.toStrictEqual(successState); expect(mockAcceptorChecks).toHaveBeenCalled(); expect(mockAcceptorChecks).toHaveBeenCalledTimes(1); @@ -69,7 +70,7 @@ describe(runPolling.name, () => { }); it("sleeps as per exponentialBackoff in case of retry", async () => { - mockAcceptorChecks = jest + mockAcceptorChecks = vi .fn() .mockResolvedValueOnce(retryState) .mockResolvedValueOnce(retryState) @@ -97,7 +98,7 @@ describe(runPolling.name, () => { it("resolves after the last attempt before reaching maxWaitTime ", async () => { let now = Date.now(); const delay = 2; - const nowMock = jest + const nowMock = vi .spyOn(Date, "now") .mockReturnValueOnce(now) // 1st invoke for getting the time stamp to wait until .mockImplementation(() => { @@ -112,7 +113,7 @@ describe(runPolling.name, () => { maxWaitTime: 5, }; - mockAcceptorChecks = jest.fn().mockResolvedValue(retryState); + mockAcceptorChecks = vi.fn().mockResolvedValue(retryState); await expect(runPolling(localConfig, input, mockAcceptorChecks)).resolves.toStrictEqual(timeoutState); expect(sleep).toHaveBeenCalled(); expect(sleep).toHaveBeenCalledTimes(2); @@ -126,7 +127,7 @@ describe(runPolling.name, () => { abortController, }; - mockAcceptorChecks = jest.fn().mockResolvedValue(retryState); + mockAcceptorChecks = vi.fn().mockResolvedValue(retryState); abortController.abort(); await expect(runPolling(localConfig, input, mockAcceptorChecks)).resolves.toStrictEqual(abortedState); expect(sleep).not.toHaveBeenCalled(); diff --git a/packages/util-waiter/src/utils/sleep.spec.ts b/packages/util-waiter/src/utils/sleep.spec.ts deleted file mode 100644 index 151aa1973a6..00000000000 --- a/packages/util-waiter/src/utils/sleep.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { sleep } from "./sleep"; - -describe("Sleep Module", () => { - beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - - describe(sleep.name, () => { - it("should call setTimeout with the proper number of milliseconds", () => { - sleep(1); - - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1000); - }); - }); -}); diff --git a/packages/util-waiter/src/utils/validate.spec.ts b/packages/util-waiter/src/utils/validate.spec.ts index bff31c85656..efde3f80c79 100644 --- a/packages/util-waiter/src/utils/validate.spec.ts +++ b/packages/util-waiter/src/utils/validate.spec.ts @@ -1,3 +1,5 @@ +import { beforeEach, describe, expect, test as it } from "vitest"; + import { WaiterOptions } from "../waiter"; import { validateWaiterOptions } from "./validate"; @@ -13,20 +15,18 @@ describe(validateWaiterOptions.name, () => { }; }); - it("should not throw an error when maxDelay is proper", (done) => { + it("should not throw an error when maxDelay is proper", () => { waiterOptions.maxDelay = 300; waiterOptions.minDelay = 200; waiterOptions.maxWaitTime = 250; try { validateWaiterOptions(waiterOptions); - expect(1).toBe(1); - done(); } catch (e) { expect(e).toBe("SHOULD NOT ERROR HERE"); } }); - it("should not throw an error when maxDelay is less than minDelay", (done) => { + it("should not throw an error when maxDelay is less than minDelay", () => { waiterOptions.maxDelay = 120; waiterOptions.minDelay = 200; waiterOptions.maxWaitTime = 250; @@ -37,34 +37,30 @@ describe(validateWaiterOptions.name, () => { expect(e.toString()).toBe( "Error: WaiterConfiguration.maxDelay [120] must be greater than WaiterConfiguration.minDelay [200] for this waiter" ); - done(); } }); - it("should not throw an error when maxWaitTime is proper", (done) => { + it("should not throw an error when maxWaitTime is proper", () => { waiterOptions.maxWaitTime = 300; waiterOptions.minDelay = 200; try { validateWaiterOptions(waiterOptions); - expect(1).toBe(1); - done(); } catch (e) { expect(e).toBe("SHOULD NOT ERROR HERE"); } }); - it("should throw when maxWaitTime is less than 0", (done) => { + it("should throw when maxWaitTime is less than 0", () => { waiterOptions.maxWaitTime = -2; waiterOptions.minDelay = -1; try { validateWaiterOptions(waiterOptions); } catch (e) { expect(e.toString()).toBe("Error: WaiterConfiguration.maxWaitTime must be greater than 0"); - done(); } }); - it("should throw when maxWaitTime is less than minDelay", (done) => { + it("should throw when maxWaitTime is less than minDelay", () => { waiterOptions.maxWaitTime = 150; waiterOptions.minDelay = 200; try { @@ -73,7 +69,6 @@ describe(validateWaiterOptions.name, () => { expect(e.toString()).toBe( "Error: WaiterConfiguration.maxWaitTime [150] must be greater than WaiterConfiguration.minDelay [200] for this waiter" ); - done(); } }); diff --git a/packages/util-waiter/src/waiter.spec.ts b/packages/util-waiter/src/waiter.spec.ts index 5829bb9098e..6dbe4a4411e 100644 --- a/packages/util-waiter/src/waiter.spec.ts +++ b/packages/util-waiter/src/waiter.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { checkExceptions, WaiterState } from "./waiter"; describe(checkExceptions.name, () => { @@ -5,34 +7,22 @@ describe(checkExceptions.name, () => { it(`throw AbortError if state is ${WaiterState.ABORTED}`, () => { const result = { state: WaiterState.ABORTED, reason }; - expect(() => checkExceptions(result)).toThrow({ - name: "AbortError", - message: JSON.stringify({ ...result, reason: "Request was aborted" }), - }); + expect(() => checkExceptions(result)).toThrowError(JSON.stringify({ ...result, reason: "Request was aborted" })); }); it(`throw TimeoutError if state is ${WaiterState.TIMEOUT}`, () => { const result = { state: WaiterState.TIMEOUT, reason }; - expect(() => checkExceptions(result)).toThrow({ - name: "TimeoutError", - message: JSON.stringify({ ...result, reason: "Waiter has timed out" }), - }); + expect(() => checkExceptions(result)).toThrowError(JSON.stringify({ ...result, reason: "Waiter has timed out" })); }); it(`throw generic Error if state is ${WaiterState.RETRY}`, () => { const result = { state: WaiterState.RETRY, reason }; - expect(() => checkExceptions(result)).toThrow({ - name: "Error", - message: JSON.stringify(result), - }); + expect(() => checkExceptions(result)).toThrow(JSON.stringify(result)); }); it(`throw generic Error if state is ${WaiterState.FAILURE}`, () => { const result = { state: WaiterState.FAILURE, reason }; - expect(() => checkExceptions(result)).toThrow({ - name: "Error", - message: JSON.stringify(result), - }); + expect(() => checkExceptions(result)).toThrow(JSON.stringify(result)); }); it(`return result if state is ${WaiterState.SUCCESS}`, () => { diff --git a/packages/util-waiter/vitest.config.ts b/packages/util-waiter/vitest.config.ts new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/packages/util-waiter/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/private/smithy-rpcv2-cbor/jest.config.js b/private/smithy-rpcv2-cbor/jest.config.js deleted file mode 100644 index a8d1c2e4991..00000000000 --- a/private/smithy-rpcv2-cbor/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts b/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts index bf9b1a52b17..ebe6175a9d5 100644 --- a/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts +++ b/private/smithy-rpcv2-cbor/test/functional/rpcv2cbor.spec.ts @@ -239,6 +239,8 @@ it("empty_input:Request", async () => { expect(r.headers["x-amz-target"]).toBeUndefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -694,6 +696,8 @@ it("no_input:Request", async () => { expect(r.headers["content-type"]).toBeUndefined(); expect(r.headers["x-amz-target"]).toBeUndefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); @@ -817,6 +821,8 @@ it.skip("RpcV2CborClientPopulatesDefaultValuesInInput:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -853,6 +859,8 @@ it.skip("RpcV2CborClientSkipsTopLevelDefaultValuesInInput:Request", async () => expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -917,6 +925,8 @@ it.skip("RpcV2CborClientUsesExplicitlyProvidedMemberValuesOverDefaults:Request", expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -956,6 +966,8 @@ it.skip("RpcV2CborClientUsesExplicitlyProvidedValuesInTopLevel:Request", async ( expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -994,6 +1006,8 @@ it.skip("RpcV2CborClientIgnoresNonTopLevelDefaultsOnMembersWithClientOptional:Re expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1155,6 +1169,8 @@ it("optional_input:Request", async () => { expect(r.headers["x-amz-target"]).toBeUndefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1234,6 +1250,8 @@ it("RpcV2CborRecursiveShapes:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RecursiveShapes"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1379,6 +1397,8 @@ it("RpcV2CborMaps:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1422,6 +1442,8 @@ it("RpcV2CborSerializesZeroValuesInMaps:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1463,6 +1485,8 @@ it("RpcV2CborSerializesDenseSetMap:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1697,6 +1721,8 @@ it("RpcV2CborLists:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1735,6 +1761,8 @@ it("RpcV2CborListsEmpty:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -1773,6 +1801,8 @@ it("RpcV2CborListsEmptyUsingDefiniteLength:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2003,6 +2033,8 @@ it("RpcV2CborSparseMaps:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2052,6 +2084,8 @@ it("RpcV2CborSerializesNullMapValues:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2093,6 +2127,8 @@ it("RpcV2CborSerializesSparseSetMap:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2135,6 +2171,8 @@ it("RpcV2CborSerializesSparseSetMapAndRetainsNull:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2178,6 +2216,8 @@ it("RpcV2CborSerializesZeroValuesInSparseMaps:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2450,6 +2490,8 @@ it("RpcV2CborSimpleScalarProperties:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2488,6 +2530,8 @@ it("RpcV2CborClientDoesntSerializeNullStructureValues:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2527,6 +2571,8 @@ it("RpcV2CborSupportsNaNFloatInputs:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2566,6 +2612,8 @@ it("RpcV2CborSupportsInfinityFloatInputs:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2605,6 +2653,8 @@ it("RpcV2CborSupportsNegativeInfinityFloatInputs:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -2982,6 +3032,8 @@ it("RpcV2CborSparseMapsSerializeNullValues:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SparseNullsOperation"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); @@ -3020,6 +3072,8 @@ it("RpcV2CborSparseListsSerializeNull:Request", async () => { expect(r.path).toBe("/service/RpcV2Protocol/operation/SparseNullsOperation"); expect(r.headers["content-length"]).toBeDefined(); + expect(r.headers["accept"]).toBeDefined(); + expect(r.headers["accept"]).toBe("application/cbor"); expect(r.headers["content-type"]).toBeDefined(); expect(r.headers["content-type"]).toBe("application/cbor"); expect(r.headers["smithy-protocol"]).toBeDefined(); diff --git a/private/smithy-rpcv2-cbor/vitest.config.js b/private/smithy-rpcv2-cbor/vitest.config.js new file mode 100644 index 00000000000..4e46707824a --- /dev/null +++ b/private/smithy-rpcv2-cbor/vitest.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["**/*.{integ,e2e,browser}.spec.ts"], + include: ["**/*.spec.ts"], + environment: "node", + }, +}); diff --git a/private/util-test/src/test-http-handler.ts b/private/util-test/src/test-http-handler.ts index 6085241e6d5..e8989ea8fd9 100644 --- a/private/util-test/src/test-http-handler.ts +++ b/private/util-test/src/test-http-handler.ts @@ -1,5 +1,6 @@ import { HttpHandler, HttpRequest, HttpResponse } from "@smithy/protocol-http"; import { Client, RequestHandler, RequestHandlerOutput } from "@smithy/types"; +import { expect } from "vitest"; /** * Instructs {@link TestHttpHandler} how to match the handled request and the expected request. diff --git a/private/util-test/tsconfig.cjs.json b/private/util-test/tsconfig.cjs.json index 1a4dd131cc4..b1c37a16934 100644 --- a/private/util-test/tsconfig.cjs.json +++ b/private/util-test/tsconfig.cjs.json @@ -3,7 +3,8 @@ "baseUrl": ".", "outDir": "dist-cjs", "rootDir": "src", - "stripInternal": true + "stripInternal": true, + "skipLibCheck": true }, "extends": "../../tsconfig.cjs.json", "include": ["src/"] diff --git a/private/util-test/tsconfig.es.json b/private/util-test/tsconfig.es.json index 0f7f061a4bb..81ffe7872ce 100644 --- a/private/util-test/tsconfig.es.json +++ b/private/util-test/tsconfig.es.json @@ -4,7 +4,8 @@ "lib": [], "outDir": "dist-es", "rootDir": "src", - "stripInternal": true + "stripInternal": true, + "skipLibCheck": true }, "extends": "../../tsconfig.es.json", "include": ["src/"] diff --git a/private/util-test/tsconfig.types.json b/private/util-test/tsconfig.types.json index 6cdf9f52ea0..9cc44fa7bc5 100644 --- a/private/util-test/tsconfig.types.json +++ b/private/util-test/tsconfig.types.json @@ -2,7 +2,8 @@ "compilerOptions": { "baseUrl": ".", "declarationDir": "dist-types", - "rootDir": "src" + "rootDir": "src", + "skipLibCheck": true }, "extends": "../../tsconfig.types.json", "include": ["src/"] diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java index 68743aae596..27be74c6cb7 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java @@ -74,7 +74,7 @@ import software.amazon.smithy.utils.SmithyInternalApi; /** - * Generates HTTP protocol test cases to be run using Jest. + * Generates HTTP protocol test cases to be run using Vitest. * *

Protocol tests are defined for HTTP protocols using the * {@code smithy.test#httpRequestTests}, {@code smithy.test#httpResponseTests} @@ -308,7 +308,7 @@ private void generateServerRequestTest(OperationShape operation, HttpRequestTest // Create a mock function to set in place of the server operation function so we can capture // input and other information. - writer.write("const testFunction = jest.fn();"); + writer.write("const testFunction = vi.fn();"); writer.write("testFunction.mockReturnValue(Promise.resolve({}));"); boolean usesDefaultValidation = !context.getSettings().isDisableDefaultValidation(); @@ -354,7 +354,7 @@ private void generateMalformedRequestTest(OperationShape operation, HttpMalforme // Create a mock function to set in place of the server operation function so we can capture // input and other information. - writer.write("const testFunction = jest.fn();"); + writer.write("const testFunction = vi.fn();"); writer.openBlock("testFunction.mockImplementation(() => {", "});", () -> { writer.write("throw new Error($S);", "This request should have been rejected."); }); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PackageJsonGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PackageJsonGenerator.java index 068edad84a0..5d1360470b5 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PackageJsonGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PackageJsonGenerator.java @@ -71,7 +71,7 @@ static void writePackageJson( ObjectNode devDeps = node.getObjectMember("devDependencies").orElse(Node.objectNode()); if (devDeps.containsMember(TypeScriptDependency.VITEST.packageName)) { ObjectNode scripts = node.getObjectMember("scripts").orElse(Node.objectNode()); - scripts = scripts.withMember("test", "vitest run --passWithNoTests"); + scripts = scripts.withMember("test", "yarn g:vitest run --passWithNoTests"); node = node.withMember("scripts", scripts); manifest.writeFile(VITEST_CONFIG_FILENAME, IoUtils.toUtf8String( diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/PackageJsonGeneratorTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/PackageJsonGeneratorTest.java index 01642245fa2..e8cf07c62e8 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/PackageJsonGeneratorTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/PackageJsonGeneratorTest.java @@ -129,7 +129,7 @@ void expectTestScriptAndTestConfigToBeAdded() { String packageJson = manifest.getFileString(PackageJsonGenerator.PACKAGE_JSON_FILENAME).get(); String configString = manifest.getFileString(PackageJsonGenerator.VITEST_CONFIG_FILENAME).get(); - assertThat(packageJson, containsString("\"test\": \"vitest run --passWithNoTests\"")); + assertThat(packageJson, containsString("\"test\": \"yarn g:vitest run --passWithNoTests\"")); assertThat(configString, containsString("include: ['**/*.spec.ts']")); } @@ -160,7 +160,7 @@ void expectTypeDocToNotBeAdded() { assertTrue(manifest.getFileString(PackageJsonGenerator.TYPEDOC_FILE_NAME).isEmpty()); String packageJson = manifest.getFileString(PackageJsonGenerator.PACKAGE_JSON_FILENAME).get(); - + assertThat(packageJson, not(containsString("\"build:docs\": \"typedoc\""))); assertThat(packageJson, not(containsString("\"typedoc\": \"0.23.23\""))); } @@ -193,7 +193,7 @@ void expectTypeDocToBeAddedWithGenerateTypeDoc() { assertTrue(manifest.getFileString(PackageJsonGenerator.TYPEDOC_FILE_NAME).isPresent()); String packageJson = manifest.getFileString(PackageJsonGenerator.PACKAGE_JSON_FILENAME).get(); - + assertThat(packageJson, containsString("\"build:docs\": \"typedoc\"")); assertThat(packageJson, containsString("\"typedoc\": \"0.23.23\"")); } diff --git a/tsconfig.json b/tsconfig.json index 37753762470..1eea5da8d40 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ "jsxFragmentFactory": "JSX.Fragment" }, "include": ["packages/", "smithy-typescript-ssdk-libs/"], - "exclude": ["node_modules/", "**/*.spec.ts"] + "exclude": ["node_modules/", "**/*.spec.ts", "vitest.*"] } diff --git a/turbo.json b/turbo.json index b7623bae3a1..2125221ebb8 100644 --- a/turbo.json +++ b/turbo.json @@ -8,12 +8,12 @@ "outputs": ["dist-types/**", "dist-cjs/**", "dist-es/**"] }, "test": { - "dependsOn": ["build"], - "outputs": [] + "dependsOn": ["build", "^build"], + "cache": false }, "test:integration": { - "dependsOn": ["build"], - "outputs": [] + "dependsOn": ["build", "^build"], + "cache": false }, "lint": { "outputs": [] diff --git a/vitest.config.integ.ts b/vitest.config.integ.ts new file mode 100644 index 00000000000..bd10f4d8459 --- /dev/null +++ b/vitest.config.integ.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: ["node_modules", "**/*.{e2e,browser}.spec.ts"], + include: ["{packages,private}/**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000000..14d2639cd86 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: [ + "node_modules", + "**/*.{integ,e2e,browser}.spec.ts", + "smithy-typescript-ssdk-libs", + "packages/chunked-blob-reader-native", + "packages/types", + "packages/util-defaults-mode-browser", + ], + include: ["packages/**/*.spec.ts", "private/**/*.spec.ts"], + environment: "node", + globals: true, + }, +}); diff --git a/yarn.lock b/yarn.lock index d5f30deb4ad..1e1cb1f8496 100644 --- a/yarn.lock +++ b/yarn.lock @@ -178,15 +178,6 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/code-frame@npm:7.22.5" - dependencies: - "@babel/highlight": ^7.22.5 - checksum: cfe804f518f53faaf9a1d3e0f9f74127ab9a004912c3a16fda07fb6a633393ecb9918a053cb71804204c1b7ec3d49e1699604715e2cfb0c9f7bc4933d324ebb6 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.2": version: 7.24.2 resolution: "@babel/code-frame@npm:7.24.2" @@ -204,13 +195,6 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/compat-data@npm:7.22.5" - checksum: eb1a47ebf79ae268b4a16903e977be52629339806e248455eb9973897c503a04b701f36a9de64e19750d6e081d0561e77a514c8dc470babbeba59ae94298ed18 - languageName: node - linkType: hard - "@babel/compat-data@npm:^7.23.5": version: 7.24.4 resolution: "@babel/compat-data@npm:7.24.4" @@ -287,29 +271,6 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.7.5": - version: 7.22.5 - resolution: "@babel/core@npm:7.22.5" - dependencies: - "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.22.5 - "@babel/generator": ^7.22.5 - "@babel/helper-compilation-targets": ^7.22.5 - "@babel/helper-module-transforms": ^7.22.5 - "@babel/helpers": ^7.22.5 - "@babel/parser": ^7.22.5 - "@babel/template": ^7.22.5 - "@babel/traverse": ^7.22.5 - "@babel/types": ^7.22.5 - convert-source-map: ^1.7.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.2 - semver: ^6.3.0 - checksum: 173ae426958c90c7bbd7de622c6f13fcab8aef0fac3f138e2d47bc466d1cd1f86f71ca82ae0acb9032fd8794abed8efb56fea55c031396337eaec0d673b69d56 - languageName: node - linkType: hard - "@babel/generator@npm:^7.21.0": version: 7.21.1 resolution: "@babel/generator@npm:7.21.1" @@ -334,18 +295,6 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/generator@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - "@jridgewell/gen-mapping": ^0.3.2 - "@jridgewell/trace-mapping": ^0.3.17 - jsesc: ^2.5.1 - checksum: efa64da70ca88fe69f05520cf5feed6eba6d30a85d32237671488cc355fdc379fe2c3246382a861d49574c4c2f82a317584f8811e95eb024e365faff3232b49d - languageName: node - linkType: hard - "@babel/generator@npm:^7.23.0": version: 7.23.0 resolution: "@babel/generator@npm:7.23.0" @@ -397,21 +346,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-compilation-targets@npm:7.22.5" - dependencies: - "@babel/compat-data": ^7.22.5 - "@babel/helper-validator-option": ^7.22.5 - browserslist: ^4.21.3 - lru-cache: ^5.1.1 - semver: ^6.3.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: a479460615acffa0f4fd0a29b740eafb53a93694265207d23a6038ccd18d183a382cacca515e77b7c9b042c3ba80b0aca0da5f1f62215140e81660d2cf721b68 - languageName: node - linkType: hard - "@babel/helper-compilation-targets@npm:^7.23.6": version: 7.23.6 resolution: "@babel/helper-compilation-targets@npm:7.23.6" @@ -439,13 +373,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-environment-visitor@npm:7.22.5" - checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 - languageName: node - linkType: hard - "@babel/helper-function-name@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-function-name@npm:7.23.0" @@ -474,15 +401,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-module-imports@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: 9ac2b0404fa38b80bdf2653fbeaf8e8a43ccb41bd505f9741d820ed95d3c4e037c62a1bcdcb6c9527d7798d2e595924c4d025daed73283badc180ada2c9c49ad - languageName: node - linkType: hard - "@babel/helper-module-imports@npm:^7.24.3": version: 7.24.3 resolution: "@babel/helper-module-imports@npm:7.24.3" @@ -508,22 +426,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-module-transforms@npm:7.22.5" - dependencies: - "@babel/helper-environment-visitor": ^7.22.5 - "@babel/helper-module-imports": ^7.22.5 - "@babel/helper-simple-access": ^7.22.5 - "@babel/helper-split-export-declaration": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.5 - "@babel/template": ^7.22.5 - "@babel/traverse": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: 8985dc0d971fd17c467e8b84fe0f50f3dd8610e33b6c86e5b3ca8e8859f9448bcc5c84e08a2a14285ef388351c0484797081c8f05a03770bf44fc27bf4900e68 - languageName: node - linkType: hard - "@babel/helper-module-transforms@npm:^7.24.5": version: 7.24.5 resolution: "@babel/helper-module-transforms@npm:7.24.5" @@ -562,15 +464,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 - languageName: node - linkType: hard - "@babel/helper-simple-access@npm:^7.24.5": version: 7.24.5 resolution: "@babel/helper-simple-access@npm:7.24.5" @@ -589,15 +482,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-split-export-declaration@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: d10e05a02f49c1f7c578cea63d2ac55356501bbf58856d97ac9bfde4957faee21ae97c7f566aa309e38a256eef58b58e5b670a7f568b362c00e93dfffe072650 - languageName: node - linkType: hard - "@babel/helper-split-export-declaration@npm:^7.22.6": version: 7.22.6 resolution: "@babel/helper-split-export-declaration@npm:7.22.6" @@ -672,13 +556,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-option@npm:7.22.5" - checksum: bbeca8a85ee86990215c0424997438b388b8d642d69b9f86c375a174d3cdeb270efafd1ff128bc7a1d370923d13b6e45829ba8581c027620e83e3a80c5c414b3 - languageName: node - linkType: hard - "@babel/helper-validator-option@npm:^7.23.5": version: 7.23.5 resolution: "@babel/helper-validator-option@npm:7.23.5" @@ -697,17 +574,6 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helpers@npm:7.22.5" - dependencies: - "@babel/template": ^7.22.5 - "@babel/traverse": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: a96e785029dff72f171190943df895ab0f76e17bf3881efd630bc5fae91215042d1c2e9ed730e8e4adf4da6f28b24bd1f54ed93b90ffbca34c197351872a084e - languageName: node - linkType: hard - "@babel/helpers@npm:^7.24.5": version: 7.24.5 resolution: "@babel/helpers@npm:7.24.5" @@ -741,17 +607,6 @@ __metadata: languageName: node linkType: hard -"@babel/highlight@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/highlight@npm:7.22.5" - dependencies: - "@babel/helper-validator-identifier": ^7.22.5 - chalk: ^2.0.0 - js-tokens: ^4.0.0 - checksum: f61ae6de6ee0ea8d9b5bcf2a532faec5ab0a1dc0f7c640e5047fc61630a0edb88b18d8c92eb06566d30da7a27db841aca11820ecd3ebe9ce514c9350fbed39c4 - languageName: node - linkType: hard - "@babel/highlight@npm:^7.24.2": version: 7.24.5 resolution: "@babel/highlight@npm:7.24.5" @@ -791,15 +646,6 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/parser@npm:7.22.5" - bin: - parser: ./bin/babel-parser.js - checksum: 470ebba516417ce8683b36e2eddd56dcfecb32c54b9bb507e28eb76b30d1c3e618fd0cfeee1f64d8357c2254514e1a19e32885cfb4e73149f4ae875436a6d59c - languageName: node - linkType: hard - "@babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.5": version: 7.24.5 resolution: "@babel/parser@npm:7.24.5" @@ -994,17 +840,6 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/template@npm:7.22.5" - dependencies: - "@babel/code-frame": ^7.22.5 - "@babel/parser": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: c5746410164039aca61829cdb42e9a55410f43cace6f51ca443313f3d0bdfa9a5a330d0b0df73dc17ef885c72104234ae05efede37c1cc8a72dc9f93425977a3 - languageName: node - linkType: hard - "@babel/template@npm:^7.24.0": version: 7.24.0 resolution: "@babel/template@npm:7.24.0" @@ -1016,7 +851,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.3, @babel/traverse@npm:^7.22.5": +"@babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.3": version: 7.23.2 resolution: "@babel/traverse@npm:7.23.2" dependencies: @@ -1374,13 +1209,6 @@ __metadata: languageName: node linkType: hard -"@colors/colors@npm:1.5.0": - version: 1.5.0 - resolution: "@colors/colors@npm:1.5.0" - checksum: d64d5260bed1d5012ae3fc617d38d1afc0329fec05342f4e6b838f46998855ba56e0a73833f4a80fa8378c84810da254f76a8a19c39d038260dc06dc4e007425 - languageName: node - linkType: hard - "@esbuild/aix-ppc64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/aix-ppc64@npm:0.19.11" @@ -1388,6 +1216,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm64@npm:0.18.20" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/android-arm64@npm:0.19.11" @@ -1395,6 +1230,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm@npm:0.18.20" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/android-arm@npm:0.19.11" @@ -1402,6 +1244,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-x64@npm:0.18.20" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/android-x64@npm:0.19.11" @@ -1409,6 +1258,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-arm64@npm:0.18.20" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/darwin-arm64@npm:0.19.11" @@ -1416,6 +1272,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-x64@npm:0.18.20" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/darwin-x64@npm:0.19.11" @@ -1423,6 +1286,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-arm64@npm:0.18.20" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/freebsd-arm64@npm:0.19.11" @@ -1430,6 +1300,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-x64@npm:0.18.20" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/freebsd-x64@npm:0.19.11" @@ -1437,6 +1314,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm64@npm:0.18.20" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-arm64@npm:0.19.11" @@ -1444,6 +1328,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm@npm:0.18.20" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-arm@npm:0.19.11" @@ -1451,6 +1342,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ia32@npm:0.18.20" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-ia32@npm:0.19.11" @@ -1458,6 +1356,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-loong64@npm:0.18.20" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-loong64@npm:0.19.11" @@ -1465,6 +1370,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-mips64el@npm:0.18.20" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-mips64el@npm:0.19.11" @@ -1472,6 +1384,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ppc64@npm:0.18.20" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-ppc64@npm:0.19.11" @@ -1479,6 +1398,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-riscv64@npm:0.18.20" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-riscv64@npm:0.19.11" @@ -1486,6 +1412,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-s390x@npm:0.18.20" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-s390x@npm:0.19.11" @@ -1493,6 +1426,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-x64@npm:0.18.20" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/linux-x64@npm:0.19.11" @@ -1500,6 +1440,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/netbsd-x64@npm:0.18.20" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/netbsd-x64@npm:0.19.11" @@ -1507,6 +1454,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/openbsd-x64@npm:0.18.20" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/openbsd-x64@npm:0.19.11" @@ -1514,6 +1468,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/sunos-x64@npm:0.18.20" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/sunos-x64@npm:0.19.11" @@ -1521,6 +1482,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-arm64@npm:0.18.20" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/win32-arm64@npm:0.19.11" @@ -1528,6 +1496,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-ia32@npm:0.18.20" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/win32-ia32@npm:0.19.11" @@ -1535,6 +1510,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-x64@npm:0.18.20" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.19.11": version: 0.19.11 resolution: "@esbuild/win32-x64@npm:0.19.11" @@ -1970,6 +1952,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.17 resolution: "@jridgewell/trace-mapping@npm:0.3.17" @@ -2298,7 +2287,6 @@ __metadata: "@types/node": ^16.18.96 concurrently: 7.0.0 downlevel-dts: 0.10.1 - nock: ^13.0.2 rimraf: 3.0.2 tslib: ^2.6.2 typedoc: 0.23.23 @@ -3156,13 +3144,6 @@ __metadata: languageName: unknown linkType: soft -"@socket.io/component-emitter@npm:~3.1.0": - version: 3.1.0 - resolution: "@socket.io/component-emitter@npm:3.1.0" - checksum: db069d95425b419de1514dffe945cc439795f6a8ef5b9465715acf5b8b50798e2c91b8719cbf5434b3fe7de179d6cdcd503c277b7871cb3dd03febb69bdd50fa - languageName: node - linkType: hard - "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -3239,19 +3220,26 @@ __metadata: languageName: node linkType: hard -"@types/cookie@npm:^0.4.1": - version: 0.4.1 - resolution: "@types/cookie@npm:0.4.1" - checksum: 3275534ed69a76c68eb1a77d547d75f99fedc80befb75a3d1d03662fb08d697e6f8b1274e12af1a74c6896071b11510631ba891f64d30c78528d0ec45a9c1a18 +"@types/chai-subset@npm:^1.3.3": + version: 1.3.5 + resolution: "@types/chai-subset@npm:1.3.5" + dependencies: + "@types/chai": "*" + checksum: 715c46d3e90f87482c2769389d560456bb257b225716ff44c275c231bdb62c8a30629f355f412bac0ecab07ebc036c1806d9ed9dde9792254f8ef4f07f76033b languageName: node linkType: hard -"@types/cors@npm:^2.8.12": - version: 2.8.13 - resolution: "@types/cors@npm:2.8.13" - dependencies: - "@types/node": "*" - checksum: 7ef197ea19d2e5bf1313b8416baa6f3fd6dd887fd70191da1f804f557395357dafd8bc8bed0ac60686923406489262a7c8a525b55748f7b2b8afa686700de907 +"@types/chai@npm:*": + version: 5.0.0 + resolution: "@types/chai@npm:5.0.0" + checksum: ae3d63d8e84b4fc7fce5b0e68d0000834e709e19378e569c9ab97503a1b38f582ff69db6299528a849ec336954690a905225cb0dd9648d823c291f53ae93b458 + languageName: node + linkType: hard + +"@types/chai@npm:^4.3.5": + version: 4.3.20 + resolution: "@types/chai@npm:4.3.20" + checksum: 7c5b0c9148f1a844a8d16cb1e16c64f2e7749cab2b8284155b9e494a6b34054846e22fb2b38df6b290f9bf57e6beebb2e121940c5896bc086ad7bab7ed429f06 languageName: node linkType: hard @@ -3333,7 +3321,7 @@ __metadata: languageName: node linkType: hard -"@types/jsdom@npm:^20.0.0": +"@types/jsdom@npm:20.0.1": version: 20.0.1 resolution: "@types/jsdom@npm:20.0.1" dependencies: @@ -3372,13 +3360,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:>=10.0.0": - version: 20.3.1 - resolution: "@types/node@npm:20.3.1" - checksum: 63a393ab6d947be17320817b35d7277ef03728e231558166ed07ee30b09fd7c08861be4d746f10fdc63ca7912e8cd023939d4eab887ff6580ff704ff24ed810c - languageName: node - linkType: hard - "@types/node@npm:^12.7.1": version: 12.20.55 resolution: "@types/node@npm:12.20.55" @@ -3422,9 +3403,9 @@ __metadata: linkType: hard "@types/tough-cookie@npm:*": - version: 4.0.2 - resolution: "@types/tough-cookie@npm:4.0.2" - checksum: e055556ffdaa39ad85ede0af192c93f93f986f4bd9e9426efdc2948e3e2632db3a4a584d4937dbf6d7620527419bc99e6182d3daf2b08685e710f2eda5291905 + version: 4.0.5 + resolution: "@types/tough-cookie@npm:4.0.5" + checksum: f19409d0190b179331586365912920d192733112a195e870c7f18d20ac8adb7ad0b0ff69dad430dba8bc2be09593453a719cfea92dc3bda19748fd158fe1498d languageName: node linkType: hard @@ -3590,6 +3571,59 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:0.34.6": + version: 0.34.6 + resolution: "@vitest/expect@npm:0.34.6" + dependencies: + "@vitest/spy": 0.34.6 + "@vitest/utils": 0.34.6 + chai: ^4.3.10 + checksum: 37a526f4af7e73fc56b71ba1139d6d93ff1972315d0e0691de967179298d2ad086e8803d2b28defe0e97a1326d808cd886e4b802d1691d8894cb234e35ed5185 + languageName: node + linkType: hard + +"@vitest/runner@npm:0.34.6": + version: 0.34.6 + resolution: "@vitest/runner@npm:0.34.6" + dependencies: + "@vitest/utils": 0.34.6 + p-limit: ^4.0.0 + pathe: ^1.1.1 + checksum: 0357f0a11f4e1e170099f9125e379bbe8049a59faa7b34b919b3e5ee8927f30824c2b3ebb814b6a77c75ec35a30bf9adb8ec2b5e051525b4edd0d17be15725cc + languageName: node + linkType: hard + +"@vitest/snapshot@npm:0.34.6": + version: 0.34.6 + resolution: "@vitest/snapshot@npm:0.34.6" + dependencies: + magic-string: ^0.30.1 + pathe: ^1.1.1 + pretty-format: ^29.5.0 + checksum: c2f164b23741cdf10f449575a0f9996cf385675d0f76d2eb696f53b614743811f2fbefdc5eb0fd3f9544ccfbb566d57a5c50a70595167458579d56429b09151f + languageName: node + linkType: hard + +"@vitest/spy@npm:0.34.6": + version: 0.34.6 + resolution: "@vitest/spy@npm:0.34.6" + dependencies: + tinyspy: ^2.1.1 + checksum: b05e5906f2f489a3234a0380a21cb48635915aa7f28eac92a595e78e9ceefb95340311635e39684b32fff20f9c58fdc33488eeddee39a660cd94c9c6bc2febf7 + languageName: node + linkType: hard + +"@vitest/utils@npm:0.34.6": + version: 0.34.6 + resolution: "@vitest/utils@npm:0.34.6" + dependencies: + diff-sequences: ^29.4.3 + loupe: ^2.3.6 + pretty-format: ^29.5.0 + checksum: acf716af2bab66037e49bd6d3e8bae40b605b9bff515d4926c46d6f8cc2366decfac5a1756ea55029968e71fba1da1f992764c3a57c9b46eccce3f6db7197bd6 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": version: 1.12.1 resolution: "@webassemblyjs/ast@npm:1.12.1" @@ -3755,13 +3789,6 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.6": - version: 2.0.6 - resolution: "abab@npm:2.0.6" - checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e - languageName: node - linkType: hard - "abbrev@npm:^1.0.0": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -3769,26 +3796,6 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.4": - version: 1.3.8 - resolution: "accepts@npm:1.3.8" - dependencies: - mime-types: ~2.1.34 - negotiator: 0.6.3 - checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 - languageName: node - linkType: hard - -"acorn-globals@npm:^7.0.0": - version: 7.0.1 - resolution: "acorn-globals@npm:7.0.1" - dependencies: - acorn: ^8.1.0 - acorn-walk: ^8.0.2 - checksum: 2a2998a547af6d0db5f0cdb90acaa7c3cbca6709010e02121fb8b8617c0fbd8bab0b869579903fde358ac78454356a14fadcc1a672ecb97b04b1c2ccba955ce8 - languageName: node - linkType: hard - "acorn-import-assertions@npm:^1.9.0": version: 1.9.0 resolution: "acorn-import-assertions@npm:1.9.0" @@ -3807,19 +3814,21 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.2": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 +"acorn-walk@npm:^8.2.0": + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" + dependencies: + acorn: ^8.11.0 + checksum: 4ff03f42323e7cf90f1683e08606b0f460e1e6ac263d2730e3df91c7665b6f64e696db6ea27ee4bed18c2599569be61f28a8399fa170c611161a348c402ca19c languageName: node linkType: hard -"acorn@npm:^8.1.0, acorn@npm:^8.8.2": - version: 8.8.2 - resolution: "acorn@npm:8.8.2" +"acorn@npm:^8.10.0, acorn@npm:^8.11.0, acorn@npm:^8.12.1": + version: 8.13.0 + resolution: "acorn@npm:8.13.0" bin: acorn: bin/acorn - checksum: f790b99a1bf63ef160c967e23c46feea7787e531292bb827126334612c234ed489a0dc2c7ba33156416f0ffa8d25bf2b0fdb7f35c2ba60eb3e960572bece4001 + checksum: f1541f05eb5d6ff67990d1927290809b1ebb663ac96d9c7057c935cf29c5bcaba6d39f37bd007f4bb814f162f142b0f2b2dd4b14128b8fcfaf9f0508a6f05f1c languageName: node linkType: hard @@ -3832,9 +3841,18 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.8.1, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.8.2": + version: 8.8.2 + resolution: "acorn@npm:8.8.2" + bin: + acorn: bin/acorn + checksum: f790b99a1bf63ef160c967e23c46feea7787e531292bb827126334612c234ed489a0dc2c7ba33156416f0ffa8d25bf2b0fdb7f35c2ba60eb3e960572bece4001 + languageName: node + linkType: hard + +"acorn@npm:^8.9.0": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" bin: acorn: bin/acorn checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c @@ -3940,7 +3958,7 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": +"anymatch@npm:^3.0.3": version: 3.1.3 resolution: "anymatch@npm:3.1.3" dependencies: @@ -4035,48 +4053,10 @@ __metadata: languageName: node linkType: hard -"asn1.js@npm:^5.2.0": - version: 5.4.1 - resolution: "asn1.js@npm:5.4.1" - dependencies: - bn.js: ^4.0.0 - inherits: ^2.0.1 - minimalistic-assert: ^1.0.0 - safer-buffer: ^2.1.0 - checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a - languageName: node - linkType: hard - -"assert@npm:^2.0.0": - version: 2.0.0 - resolution: "assert@npm:2.0.0" - dependencies: - es6-object-assign: ^1.1.0 - is-nan: ^1.2.1 - object-is: ^1.0.1 - util: ^0.12.0 - checksum: bb91f181a86d10588ee16c5e09c280f9811373974c29974cbe401987ea34e966699d7989a812b0e19377b511ea0bc627f5905647ce569311824848ede382cae8 - languageName: node - linkType: hard - -"async@npm:^3.0.1": - version: 3.2.4 - resolution: "async@npm:3.2.4" - checksum: 43d07459a4e1d09b84a20772414aa684ff4de085cbcaec6eea3c7a8f8150e8c62aa6cd4e699fe8ee93c3a5b324e777d34642531875a0817a35697522c1b02e89 - languageName: node - linkType: hard - -"asynckit@npm:^0.4.0": - version: 0.4.0 - resolution: "asynckit@npm:0.4.0" - checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be - languageName: node - linkType: hard - -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf languageName: node linkType: hard @@ -4179,13 +4159,6 @@ __metadata: languageName: node linkType: hard -"base64id@npm:2.0.0, base64id@npm:~2.0.0": - version: 2.0.0 - resolution: "base64id@npm:2.0.0" - checksum: 581b1d37e6cf3738b7ccdd4d14fe2bfc5c238e696e2720ee6c44c183b838655842e22034e53ffd783f872a539915c51b0d4728a49c7cc678ac5a758e00d62168 - languageName: node - linkType: hard - "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -4202,13 +4175,6 @@ __metadata: languageName: node linkType: hard -"binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 - languageName: node - linkType: hard - "bl@npm:^4.0.3": version: 4.1.0 resolution: "bl@npm:4.1.0" @@ -4220,40 +4186,6 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 - languageName: node - linkType: hard - -"bn.js@npm:^5.0.0, bn.js@npm:^5.2.1": - version: 5.2.1 - resolution: "bn.js@npm:5.2.1" - checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 - languageName: node - linkType: hard - -"body-parser@npm:^1.19.0": - version: 1.20.2 - resolution: "body-parser@npm:1.20.2" - dependencies: - bytes: 3.1.2 - content-type: ~1.0.5 - 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.11.0 - raw-body: 2.5.2 - type-is: ~1.6.18 - unpipe: 1.0.0 - checksum: 14d37ec638ab5c93f6099ecaed7f28f890d222c650c69306872e00b9efa081ff6c596cd9afb9930656aae4d6c4e1c17537bea12bb73c87a217cb3cfea8896737 - languageName: node - linkType: hard - "bowser@npm:^2.11.0": version: 2.11.0 resolution: "bowser@npm:2.11.0" @@ -4280,7 +4212,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:^3.0.3, braces@npm:~3.0.2": +"braces@npm:^3.0.2, braces@npm:^3.0.3": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -4298,95 +4230,6 @@ __metadata: languageName: node linkType: hard -"brorand@npm:^1.0.1, brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be - languageName: node - linkType: hard - -"browser-resolve@npm:^2.0.0": - version: 2.0.0 - resolution: "browser-resolve@npm:2.0.0" - dependencies: - resolve: ^1.17.0 - checksum: 69225e73b555bd6d2a08fb93c7342cfcf3b5058b975099c52649cd5c3cec84c2066c5385084d190faedfb849684d9dabe10129f0cd401d1883572f2e6650f440 - languageName: node - linkType: hard - -"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4": - version: 1.2.0 - resolution: "browserify-aes@npm:1.2.0" - dependencies: - buffer-xor: ^1.0.3 - cipher-base: ^1.0.0 - create-hash: ^1.1.0 - evp_bytestokey: ^1.0.3 - inherits: ^2.0.1 - safe-buffer: ^5.0.1 - checksum: 4a17c3eb55a2aa61c934c286f34921933086bf6d67f02d4adb09fcc6f2fc93977b47d9d884c25619144fccd47b3b3a399e1ad8b3ff5a346be47270114bcf7104 - languageName: node - linkType: hard - -"browserify-cipher@npm:^1.0.0": - version: 1.0.1 - resolution: "browserify-cipher@npm:1.0.1" - dependencies: - browserify-aes: ^1.0.4 - browserify-des: ^1.0.0 - evp_bytestokey: ^1.0.0 - checksum: 2d8500acf1ee535e6bebe808f7a20e4c3a9e2ed1a6885fff1facbfd201ac013ef030422bec65ca9ece8ffe82b03ca580421463f9c45af6c8415fd629f4118c13 - languageName: node - linkType: hard - -"browserify-des@npm:^1.0.0": - version: 1.0.2 - resolution: "browserify-des@npm:1.0.2" - dependencies: - cipher-base: ^1.0.1 - des.js: ^1.0.0 - inherits: ^2.0.1 - safe-buffer: ^5.1.2 - checksum: b15a3e358a1d78a3b62ddc06c845d02afde6fc826dab23f1b9c016e643e7b1fda41de628d2110b712f6a44fb10cbc1800bc6872a03ddd363fb50768e010395b7 - languageName: node - linkType: hard - -"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.0": - version: 4.1.0 - resolution: "browserify-rsa@npm:4.1.0" - dependencies: - bn.js: ^5.0.0 - randombytes: ^2.0.1 - checksum: 155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54 - languageName: node - linkType: hard - -"browserify-sign@npm:^4.0.0": - version: 4.2.2 - resolution: "browserify-sign@npm:4.2.2" - dependencies: - bn.js: ^5.2.1 - browserify-rsa: ^4.1.0 - create-hash: ^1.2.0 - create-hmac: ^1.1.7 - elliptic: ^6.5.4 - inherits: ^2.0.4 - parse-asn1: ^5.1.6 - readable-stream: ^3.6.2 - safe-buffer: ^5.2.1 - checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c - languageName: node - linkType: hard - -"browserify-zlib@npm:^0.2.0": - version: 0.2.0 - resolution: "browserify-zlib@npm:0.2.0" - dependencies: - pako: ~1.0.5 - checksum: 5cd9d6a665190fedb4a97dfbad8dabc8698d8a507298a03f42c734e96d58ca35d3c7d4085e283440bbca1cd1938cff85031728079bedb3345310c58ab1ec92d6 - languageName: node - linkType: hard - "browserslist@npm:^4.21.10, browserslist@npm:^4.22.2": version: 4.23.0 resolution: "browserslist@npm:4.23.0" @@ -4447,14 +4290,7 @@ __metadata: languageName: node linkType: hard -"buffer-xor@npm:^1.0.3": - version: 1.0.3 - resolution: "buffer-xor@npm:1.0.3" - checksum: 10c520df29d62fa6e785e2800e586a20fc4f6dfad84bcdbd12e1e8a83856de1cb75c7ebd7abe6d036bbfab738a6cf18a3ae9c8e5a2e2eb3167ca7399ce65373a - languageName: node - linkType: hard - -"buffer@npm:^5.2.1, buffer@npm:^5.4.3, buffer@npm:^5.5.0": +"buffer@npm:^5.2.1, buffer@npm:^5.5.0": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -4464,17 +4300,10 @@ __metadata: languageName: node linkType: hard -"builtin-status-codes@npm:^3.0.0": - version: 3.0.0 - resolution: "builtin-status-codes@npm:3.0.0" - checksum: 1119429cf4b0d57bf76b248ad6f529167d343156ebbcc4d4e4ad600484f6bc63002595cbb61b67ad03ce55cd1d3c4711c03bbf198bf24653b8392420482f3773 - languageName: node - linkType: hard - -"bytes@npm:3.1.2": - version: 3.1.2 - resolution: "bytes@npm:3.1.2" - checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a languageName: node linkType: hard @@ -4573,6 +4402,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.10": + version: 4.5.0 + resolution: "chai@npm:4.5.0" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.1.0 + checksum: 70e5a8418a39e577e66a441cc0ce4f71fd551a650a71de30dd4e3e31e75ed1f5aa7119cf4baf4a2cb5e85c0c6befdb4d8a05811fad8738c1a6f3aa6a23803821 + languageName: node + linkType: hard + "chalk@npm:^2.0.0, chalk@npm:^2.1.0, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -4608,22 +4452,12 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.5.1": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" dependencies: - anymatch: ~3.1.2 - braces: ~3.0.2 - fsevents: ~2.3.2 - glob-parent: ~5.1.2 - is-binary-path: ~2.1.0 - is-glob: ~4.0.1 - normalize-path: ~3.0.0 - readdirp: ~3.6.0 - dependenciesMeta: - fsevents: - optional: true - checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 languageName: node linkType: hard @@ -4680,16 +4514,6 @@ __metadata: languageName: node linkType: hard -"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.4 - resolution: "cipher-base@npm:1.0.4" - dependencies: - inherits: ^2.0.1 - safe-buffer: ^5.0.1 - checksum: 47d3568dbc17431a339bad1fe7dff83ac0891be8206911ace3d3b818fc695f376df809bea406e759cdea07fff4b454fa25f1013e648851bec790c1d75763032e - languageName: node - linkType: hard - "cjs-module-lexer@npm:^1.0.0": version: 1.2.2 resolution: "cjs-module-lexer@npm:1.2.2" @@ -4806,27 +4630,6 @@ __metadata: languageName: node linkType: hard -"combine-source-map@npm:^0.8.0": - version: 0.8.0 - resolution: "combine-source-map@npm:0.8.0" - dependencies: - convert-source-map: ~1.1.0 - inline-source-map: ~0.6.0 - lodash.memoize: ~3.0.3 - source-map: ~0.5.3 - checksum: 26b3064a4e58400e04089acbf5c8741c47db079706bb2fcd79a7768f99d68de9baf1eb48081cdfbc568e308633105af2aeaf52c73e388619ba1f56463fb73a2e - languageName: node - linkType: hard - -"combined-stream@npm:^1.0.8": - version: 1.0.8 - resolution: "combined-stream@npm:1.0.8" - dependencies: - delayed-stream: ~1.0.0 - checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c - languageName: node - linkType: hard - "commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -4873,22 +4676,10 @@ __metadata: languageName: node linkType: hard -"connect@npm:^3.7.0": - version: 3.7.0 - resolution: "connect@npm:3.7.0" - dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 - parseurl: ~1.3.3 - utils-merge: 1.0.1 - checksum: 96e1c4effcf219b065c7823e57351c94366d2e2a6952fa95e8212bffb35c86f1d5a3f9f6c5796d4cd3a5fdda628368b1c3cc44bf19c66cfd68fe9f9cab9177e2 - languageName: node - linkType: hard - -"console-browserify@npm:^1.2.0": - version: 1.2.0 - resolution: "console-browserify@npm:1.2.0" - checksum: 226591eeff8ed68e451dffb924c1fb750c654d54b9059b3b261d360f369d1f8f70650adecf2c7136656236a4bfeb55c39281b5d8a55d792ebbb99efd3d848d52 +"confbox@npm:^0.1.8": + version: 0.1.8 + resolution: "confbox@npm:0.1.8" + checksum: 5c7718ab22cf9e35a31c21ef124156076ae8c9dc65e6463d54961caf5a1d529284485a0fdf83fd23b27329f3b75b0c8c07d2e36c699f5151a2efe903343f976a languageName: node linkType: hard @@ -4899,20 +4690,6 @@ __metadata: languageName: node linkType: hard -"constants-browserify@npm:^1.0.0": - version: 1.0.0 - resolution: "constants-browserify@npm:1.0.0" - checksum: f7ac8c6d0b6e4e0c77340a1d47a3574e25abd580bfd99ad707b26ff7618596cf1a5e5ce9caf44715e9e01d4a5d12cb3b4edaf1176f34c19adb2874815a56e64f - languageName: node - linkType: hard - -"content-type@npm:~1.0.5": - version: 1.0.5 - resolution: "content-type@npm:1.0.5" - checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 - languageName: node - linkType: hard - "convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" @@ -4927,30 +4704,6 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:~1.1.0": - version: 1.1.3 - resolution: "convert-source-map@npm:1.1.3" - checksum: 0ed6bdecd330fd05941b417b63ebc9001b438f6d6681cd9a068617c3d4b649794dc35c95ba239d0a01f0b9499912b9e0d0d1b7c612e3669c57c65ce4bbc8fdd8 - languageName: node - linkType: hard - -"cookie@npm:~0.4.1": - version: 0.4.2 - resolution: "cookie@npm:0.4.2" - checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b - languageName: node - linkType: hard - -"cors@npm:~2.8.5": - version: 2.8.5 - resolution: "cors@npm:2.8.5" - dependencies: - object-assign: ^4 - vary: ^1 - checksum: ced838404ccd184f61ab4fdc5847035b681c90db7ac17e428f3d81d69e2989d2b680cc254da0e2554f5ed4f8a341820a1ce3d1c16b499f6e2f47a1b9b07b5006 - languageName: node - linkType: hard - "cosmiconfig@npm:8.1.3": version: 8.1.3 resolution: "cosmiconfig@npm:8.1.3" @@ -4976,43 +4729,6 @@ __metadata: languageName: node linkType: hard -"create-ecdh@npm:^4.0.0": - version: 4.0.4 - resolution: "create-ecdh@npm:4.0.4" - dependencies: - bn.js: ^4.1.0 - elliptic: ^6.5.3 - checksum: 0dd7fca9711d09e152375b79acf1e3f306d1a25ba87b8ff14c2fd8e68b83aafe0a7dd6c4e540c9ffbdd227a5fa1ad9b81eca1f233c38bb47770597ba247e614b - languageName: node - linkType: hard - -"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": - version: 1.2.0 - resolution: "create-hash@npm:1.2.0" - dependencies: - cipher-base: ^1.0.1 - inherits: ^2.0.1 - md5.js: ^1.3.4 - ripemd160: ^2.0.1 - sha.js: ^2.4.0 - checksum: 02a6ae3bb9cd4afee3fabd846c1d8426a0e6b495560a977ba46120c473cb283be6aa1cace76b5f927cf4e499c6146fb798253e48e83d522feba807d6b722eaa9 - languageName: node - linkType: hard - -"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": - version: 1.1.7 - resolution: "create-hmac@npm:1.1.7" - dependencies: - cipher-base: ^1.0.3 - create-hash: ^1.1.0 - inherits: ^2.0.1 - ripemd160: ^2.0.0 - safe-buffer: ^5.0.1 - sha.js: ^2.4.8 - checksum: ba12bb2257b585a0396108c72830e85f882ab659c3320c83584b1037f8ab72415095167ced80dc4ce8e446a8ecc4b2acf36d87befe0707d73b26cf9dc77440ed - languageName: node - linkType: hard - "create-jest@npm:^29.7.0": version: 29.7.0 resolution: "create-jest@npm:29.7.0" @@ -5061,48 +4777,6 @@ __metadata: languageName: node linkType: hard -"crypto-browserify@npm:^3.12.0": - version: 3.12.0 - resolution: "crypto-browserify@npm:3.12.0" - dependencies: - browserify-cipher: ^1.0.0 - browserify-sign: ^4.0.0 - create-ecdh: ^4.0.0 - create-hash: ^1.1.0 - create-hmac: ^1.1.0 - diffie-hellman: ^5.0.0 - inherits: ^2.0.1 - pbkdf2: ^3.0.3 - public-encrypt: ^4.0.0 - randombytes: ^2.0.0 - randomfill: ^1.0.3 - checksum: c1609af82605474262f3eaa07daa0b2140026bd264ab316d4bf1170272570dbe02f0c49e29407fe0d3634f96c507c27a19a6765fb856fed854a625f9d15618e2 - languageName: node - linkType: hard - -"cssom@npm:^0.5.0": - version: 0.5.0 - resolution: "cssom@npm:0.5.0" - checksum: 823471aa30091c59e0a305927c30e7768939b6af70405808f8d2ce1ca778cddcb24722717392438329d1691f9a87cb0183b64b8d779b56a961546d54854fde01 - languageName: node - linkType: hard - -"cssom@npm:~0.3.6": - version: 0.3.8 - resolution: "cssom@npm:0.3.8" - checksum: 24beb3087c76c0d52dd458be9ee1fbc80ac771478a9baef35dd258cdeb527c68eb43204dd439692bb2b1ae5272fa5f2946d10946edab0d04f1078f85e06bc7f6 - languageName: node - linkType: hard - -"cssstyle@npm:^2.3.0": - version: 2.3.0 - resolution: "cssstyle@npm:2.3.0" - dependencies: - cssom: ~0.3.6 - checksum: 5f05e6fd2e3df0b44695c2f08b9ef38b011862b274e320665176467c0725e44a53e341bc4959a41176e83b66064ab786262e7380fd1cabeae6efee0d255bb4e3 - languageName: node - linkType: hard - "csv-generate@npm:^3.4.3": version: 3.4.3 resolution: "csv-generate@npm:3.4.3" @@ -5136,24 +4810,6 @@ __metadata: languageName: node linkType: hard -"custom-event@npm:~1.0.0": - version: 1.0.1 - resolution: "custom-event@npm:1.0.1" - checksum: 334f48a6d5fb98df95c5f72cab2729417ffdcc74aebb1d51aa9220391bdee028ec36d9e19976a5a64f536e1e4aceb5bb4f0232d4761acc3e8fd74c54573959bd - languageName: node - linkType: hard - -"data-urls@npm:^3.0.2": - version: 3.0.2 - resolution: "data-urls@npm:3.0.2" - dependencies: - abab: ^2.0.6 - whatwg-mimetype: ^3.0.0 - whatwg-url: ^11.0.0 - checksum: 033fc3dd0fba6d24bc9a024ddcf9923691dd24f90a3d26f6545d6a2f71ec6956f93462f2cdf2183cc46f10dc01ed3bcb36731a8208456eb1a08147e571fe2a76 - languageName: node - linkType: hard - "data-view-buffer@npm:^1.0.1": version: 1.0.1 resolution: "data-view-buffer@npm:1.0.1" @@ -5194,23 +4850,7 @@ __metadata: languageName: node linkType: hard -"date-format@npm:^4.0.14": - version: 4.0.14 - resolution: "date-format@npm:4.0.14" - checksum: dfe5139df6af5759b9dd3c007b899b3f60d45a9240ffeee6314ab74e6ab52e9b519a44ccf285888bdd6b626c66ee9b4c8a523075fa1140617b5beb1cbb9b18d1 - languageName: node - linkType: hard - -"debug@npm:2.6.9": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: 2.0.0 - checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -5239,13 +4879,6 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.2": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 796404dcfa9d1dbfdc48870229d57f788b48c21c603c3f6554a1c17c10195fc1024de338b0cf9e1efe0c7c167eeb18f04548979bcc5fdfabebb7cc0ae3287bae - languageName: node - linkType: hard - "dedent@npm:^1.0.0": version: 1.5.3 resolution: "dedent@npm:1.5.3" @@ -5258,7 +4891,16 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": +"deep-eql@npm:^4.1.3": + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" + dependencies: + type-detect: ^4.0.0 + checksum: 01c3ca78ff40d79003621b157054871411f94228ceb9b2cab78da913c606631c46e8aa79efc4aa0faf3ace3092acd5221255aab3ef0e8e7b438834f0ca9a16c7 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 @@ -5292,16 +4934,6 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3": - version: 1.2.0 - resolution: "define-properties@npm:1.2.0" - dependencies: - has-property-descriptors: ^1.0.0 - object-keys: ^1.1.1 - checksum: e60aee6a19b102df4e2b1f301816804e81ab48bb91f00d0d935f269bf4b3f79c88b39e4f89eaa132890d23267335fd1140dfcd8d5ccd61031a0a2c41a54e33a6 - languageName: node - linkType: hard - "define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" @@ -5313,13 +4945,6 @@ __metadata: languageName: node linkType: hard -"delayed-stream@npm:~1.0.0": - version: 1.0.0 - resolution: "delayed-stream@npm:1.0.0" - checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020 - languageName: node - linkType: hard - "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -5327,30 +4952,13 @@ __metadata: languageName: node linkType: hard -"depd@npm:2.0.0, depd@npm:^2.0.0": +"depd@npm:^2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a languageName: node linkType: hard -"des.js@npm:^1.0.0": - version: 1.1.0 - resolution: "des.js@npm:1.1.0" - dependencies: - inherits: ^2.0.1 - minimalistic-assert: ^1.0.0 - checksum: 0e9c1584b70d31e20f20a613fc9ef60fbc6a147dfec9e448a168794a4b97ac04d8dc47ea008f1fa93b0f8aaf7c1ead632a5e59ce1913a6079d2d244c9f5ebe33 - languageName: node - linkType: hard - -"destroy@npm:1.2.0": - version: 1.2.0 - resolution: "destroy@npm:1.2.0" - checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 - languageName: node - linkType: hard - "detect-indent@npm:^6.0.0": version: 6.1.0 resolution: "detect-indent@npm:6.1.0" @@ -5372,13 +4980,6 @@ __metadata: languageName: node linkType: hard -"di@npm:^0.0.1": - version: 0.0.1 - resolution: "di@npm:0.0.1" - checksum: 3f09a99534d33e49264585db7f863ea8bc76c25c4d5a60df387c946018ecf1e1516b2c05a2092e5ca51fcdc08cefe609a6adc5253fa831626cb78cad4746505e - languageName: node - linkType: hard - "diff-sequences@npm:^28.1.1": version: 28.1.1 resolution: "diff-sequences@npm:28.1.1" @@ -5386,31 +4987,13 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": +"diff-sequences@npm:^29.4.3, diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa languageName: node linkType: hard -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d - languageName: node - linkType: hard - -"diffie-hellman@npm:^5.0.0": - version: 5.0.3 - resolution: "diffie-hellman@npm:5.0.3" - dependencies: - bn.js: ^4.1.0 - miller-rabin: ^4.0.0 - randombytes: ^2.0.0 - checksum: 0e620f322170c41076e70181dd1c24e23b08b47dbb92a22a644f3b89b6d3834b0f8ee19e37916164e5eb1ee26d2aa836d6129f92723995267250a0b541811065 - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -5429,34 +5012,6 @@ __metadata: languageName: node linkType: hard -"dom-serialize@npm:^2.2.1": - version: 2.2.1 - resolution: "dom-serialize@npm:2.2.1" - dependencies: - custom-event: ~1.0.0 - ent: ~2.2.0 - extend: ^3.0.0 - void-elements: ^2.0.0 - checksum: 48262e299a694dbfa32905ecceb29b89f2ce59adfc00cb676284f85ee0c8db0225e07961cbf9b06bf309291deebf52c958f855a5b6709d556000acf46d5a46ef - languageName: node - linkType: hard - -"domain-browser@npm:^4.16.0": - version: 4.22.0 - resolution: "domain-browser@npm:4.22.0" - checksum: e7ce1c19073e17dec35cfde050a3ddaac437d3ba8b870adabf9d5682e665eab3084df05de432dedf25b34303f0a2c71ac30f1cdba61b1aea018047b10de3d988 - languageName: node - linkType: hard - -"domexception@npm:^4.0.0": - version: 4.0.0 - resolution: "domexception@npm:4.0.0" - dependencies: - webidl-conversions: ^7.0.0 - checksum: ddbc1268edf33a8ba02ccc596735ede80375ee0cf124b30d2f05df5b464ba78ef4f49889b6391df4a04954e63d42d5631c7fcf8b1c4f12bc531252977a5f13d5 - languageName: node - linkType: hard - "downlevel-dts@npm:0.10.1": version: 0.10.1 resolution: "downlevel-dts@npm:0.10.1" @@ -5483,13 +5038,6 @@ __metadata: languageName: node linkType: hard -"ee-first@npm:1.1.1": - version: 1.1.1 - resolution: "ee-first@npm:1.1.1" - checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f - languageName: node - linkType: hard - "electron-to-chromium@npm:^1.4.284": version: 1.4.320 resolution: "electron-to-chromium@npm:1.4.320" @@ -5504,21 +5052,6 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": - version: 6.5.4 - resolution: "elliptic@npm:6.5.4" - dependencies: - bn.js: ^4.11.9 - brorand: ^1.1.0 - hash.js: ^1.0.0 - hmac-drbg: ^1.0.1 - inherits: ^2.0.4 - minimalistic-assert: ^1.0.1 - minimalistic-crypto-utils: ^1.0.1 - checksum: d56d21fd04e97869f7ffcc92e18903b9f67f2d4637a23c860492fbbff5a3155fd9ca0184ce0c865dd6eb2487d234ce9551335c021c376cd2d3b7cb749c7d10f4 - languageName: node - linkType: hard - "emittery@npm:^0.13.1": version: 0.13.1 resolution: "emittery@npm:0.13.1" @@ -5533,13 +5066,6 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:~1.0.2": - version: 1.0.2 - resolution: "encodeurl@npm:1.0.2" - checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c - languageName: node - linkType: hard - "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -5558,31 +5084,6 @@ __metadata: languageName: node linkType: hard -"engine.io-parser@npm:~5.2.1": - version: 5.2.2 - resolution: "engine.io-parser@npm:5.2.2" - checksum: 470231215f3136a9259efb1268bc9a71f789af4e8c74da8d3b49ceb149fe3cd5c315bf0cd13d2d8d9c8f0f051c6f93b68e8fa9c89a3b612b9217bf33765c943a - languageName: node - linkType: hard - -"engine.io@npm:~6.5.2": - version: 6.5.4 - resolution: "engine.io@npm:6.5.4" - 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.2.1 - ws: ~8.11.0 - checksum: d5b55cbac718c5b1c10800314379923f8c7ef9e3a8a60c6827ed86303d1154b81d354a89fdecf4cbb773515c82c84a98d3c791ff88279393b53625dd67299d30 - languageName: node - linkType: hard - "enhanced-resolve@npm:^5.16.0": version: 5.16.1 resolution: "enhanced-resolve@npm:5.16.1" @@ -5603,14 +5104,7 @@ __metadata: languageName: node linkType: hard -"ent@npm:~2.2.0": - version: 2.2.0 - resolution: "ent@npm:2.2.0" - checksum: f588b5707d6fef36011ea10d530645912a69530a1eb0831f8708c498ac028363a7009f45cfadd28ceb4dafd9ac17ec15213f88d09ce239cd033cfe1328dd7d7d - languageName: node - linkType: hard - -"entities@npm:^4.4.0": +"entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 @@ -5757,13 +5251,6 @@ __metadata: languageName: node linkType: hard -"es6-object-assign@npm:^1.1.0": - version: 1.1.0 - resolution: "es6-object-assign@npm:1.1.0" - checksum: 8d4fdf63484d78b5c64cacc2c2e1165bc7b6a64b739d2a9db6a4dc8641d99cc9efb433cdd4dc3d3d6b00bfa6ce959694e4665e3255190339945c5f33b692b5d8 - languageName: node - linkType: hard - "esbuild@npm:0.19.11": version: 0.19.11 resolution: "esbuild@npm:0.19.11" @@ -5840,7 +5327,84 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: ae949a796d1d06b55275ae7491ce137857468f69a93d8cc9c0943d2a701ac54e14dbb250a2ba56f2ad98283669578f1ec3bd85a4681910a5ff29a2470c3bd62c + checksum: ae949a796d1d06b55275ae7491ce137857468f69a93d8cc9c0943d2a701ac54e14dbb250a2ba56f2ad98283669578f1ec3bd85a4681910a5ff29a2470c3bd62c + languageName: node + linkType: hard + +"esbuild@npm:^0.18.10": + version: 0.18.20 + resolution: "esbuild@npm:0.18.20" + dependencies: + "@esbuild/android-arm": 0.18.20 + "@esbuild/android-arm64": 0.18.20 + "@esbuild/android-x64": 0.18.20 + "@esbuild/darwin-arm64": 0.18.20 + "@esbuild/darwin-x64": 0.18.20 + "@esbuild/freebsd-arm64": 0.18.20 + "@esbuild/freebsd-x64": 0.18.20 + "@esbuild/linux-arm": 0.18.20 + "@esbuild/linux-arm64": 0.18.20 + "@esbuild/linux-ia32": 0.18.20 + "@esbuild/linux-loong64": 0.18.20 + "@esbuild/linux-mips64el": 0.18.20 + "@esbuild/linux-ppc64": 0.18.20 + "@esbuild/linux-riscv64": 0.18.20 + "@esbuild/linux-s390x": 0.18.20 + "@esbuild/linux-x64": 0.18.20 + "@esbuild/netbsd-x64": 0.18.20 + "@esbuild/openbsd-x64": 0.18.20 + "@esbuild/sunos-x64": 0.18.20 + "@esbuild/win32-arm64": 0.18.20 + "@esbuild/win32-ia32": 0.18.20 + "@esbuild/win32-x64": 0.18.20 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b languageName: node linkType: hard @@ -5858,13 +5422,6 @@ __metadata: languageName: node linkType: hard -"escape-html@npm:~1.0.3": - version: 1.0.3 - resolution: "escape-html@npm:1.0.3" - checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 - languageName: node - linkType: hard - "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -5886,25 +5443,6 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.0.0": - version: 2.0.0 - resolution: "escodegen@npm:2.0.0" - dependencies: - esprima: ^4.0.1 - estraverse: ^5.2.0 - esutils: ^2.0.2 - optionator: ^0.8.1 - source-map: ~0.6.1 - dependenciesMeta: - source-map: - optional: true - bin: - escodegen: bin/escodegen.js - esgenerate: bin/esgenerate.js - checksum: 5aa6b2966fafe0545e4e77936300cc94ad57cfe4dc4ebff9950492eaba83eef634503f12d7e3cbd644ecc1bab388ad0e92b06fd32222c9281a75d1cf02ec6cef - languageName: node - linkType: hard - "eslint-plugin-simple-import-sort@npm:7.0.0": version: 7.0.0 resolution: "eslint-plugin-simple-import-sort@npm:7.0.0" @@ -6010,7 +5548,7 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0, esprima@npm:^4.0.1": +"esprima@npm:^4.0.0": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -6059,13 +5597,6 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.0": - version: 4.0.7 - resolution: "eventemitter3@npm:4.0.7" - checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 - languageName: node - linkType: hard - "events@npm:^3.2.0": version: 3.3.0 resolution: "events@npm:3.3.0" @@ -6073,17 +5604,6 @@ __metadata: languageName: node linkType: hard -"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": - version: 1.0.3 - resolution: "evp_bytestokey@npm:1.0.3" - dependencies: - md5.js: ^1.3.4 - node-gyp: latest - safe-buffer: ^5.1.1 - checksum: ad4e1577f1a6b721c7800dcc7c733fe01f6c310732bb5bf2240245c2a5b45a38518b91d8be2c610611623160b9d1c0e91f1ce96d639f8b53e8894625cf20fa45 - languageName: node - linkType: hard - "execa@npm:^5.0.0": version: 5.1.1 resolution: "execa@npm:5.1.1" @@ -6121,13 +5641,6 @@ __metadata: languageName: node linkType: hard -"extend@npm:^3.0.0": - version: 3.0.2 - resolution: "extend@npm:3.0.2" - checksum: a50a8309ca65ea5d426382ff09f33586527882cf532931cb08ca786ea3146c0553310bda688710ff61d7668eba9f96b923fe1420cdf56a2c3eaf30fcab87b515 - languageName: node - linkType: hard - "extendable-error@npm:^0.1.5": version: 0.1.7 resolution: "extendable-error@npm:0.1.7" @@ -6190,7 +5703,7 @@ __metadata: languageName: node linkType: hard -"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": +"fast-levenshtein@npm:^2.0.6": version: 2.0.6 resolution: "fast-levenshtein@npm:2.0.6" checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c @@ -6249,21 +5762,6 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:1.1.2": - version: 1.1.2 - resolution: "finalhandler@npm:1.1.2" - 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 - checksum: 617880460c5138dd7ccfd555cb5dde4d8f170f4b31b8bd51e4b646bb2946c30f7db716428a1f2882d730d2b72afb47d1f67cc487b874cb15426f95753a88965e - languageName: node - linkType: hard - "find-up@npm:^4.0.0, find-up@npm:^4.1.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" @@ -6313,23 +5811,13 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.1.0, flatted@npm:^3.2.7": +"flatted@npm:^3.1.0": version: 3.2.7 resolution: "flatted@npm:3.2.7" checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 languageName: node linkType: hard -"follow-redirects@npm:^1.0.0": - version: 1.15.6 - resolution: "follow-redirects@npm:1.15.6" - peerDependenciesMeta: - debug: - optional: true - checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 - languageName: node - linkType: hard - "for-each@npm:^0.3.3": version: 0.3.3 resolution: "for-each@npm:0.3.3" @@ -6339,17 +5827,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" - dependencies: - asynckit: ^0.4.0 - combined-stream: ^1.0.8 - mime-types: ^2.1.12 - checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c - languageName: node - linkType: hard - "fs-constants@npm:^1.0.0": version: 1.0.0 resolution: "fs-constants@npm:1.0.0" @@ -6477,6 +5954,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + "get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3": version: 1.2.0 resolution: "get-intrinsic@npm:1.2.0" @@ -6508,6 +5992,13 @@ __metadata: languageName: node linkType: hard +"get-port@npm:^7.1.0": + version: 7.1.0 + resolution: "get-port@npm:7.1.0" + checksum: f4d23b43026124007663a899578cc87ff37bfcf645c5c72651e9810ebafc759857784e409fb8e0ada9b90e5c5db089b0ae2f5f6b49fba1ce2e0aff86094ab17d + languageName: node + linkType: hard + "get-stream@npm:^5.1.0": version: 5.2.0 resolution: "get-stream@npm:5.2.0" @@ -6535,7 +6026,7 @@ __metadata: languageName: node linkType: hard -"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": +"glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" dependencies: @@ -6560,7 +6051,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7": +"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -6664,6 +6155,17 @@ __metadata: languageName: node linkType: hard +"happy-dom@npm:14.12.3": + version: 14.12.3 + resolution: "happy-dom@npm:14.12.3" + dependencies: + entities: ^4.5.0 + webidl-conversions: ^7.0.0 + whatwg-mimetype: ^3.0.0 + checksum: 9d5bc8d5aea3f07f5050e5a82aaa0b0063feee43f99755de5e0ca01ce328f0282c183085ad83404a777a02d7bea98bd13b8fedb0dc566d4df7563bf4287282ad + languageName: node + linkType: hard + "hard-rejection@npm:^2.1.0": version: 2.1.0 resolution: "hard-rejection@npm:2.1.0" @@ -6758,17 +6260,6 @@ __metadata: languageName: node linkType: hard -"hash-base@npm:^3.0.0": - version: 3.1.0 - resolution: "hash-base@npm:3.1.0" - dependencies: - inherits: ^2.0.4 - readable-stream: ^3.6.0 - safe-buffer: ^5.2.0 - checksum: 26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc - languageName: node - linkType: hard - "hash-test-vectors@npm:^1.3.2": version: 1.3.2 resolution: "hash-test-vectors@npm:1.3.2" @@ -6776,16 +6267,6 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: ^2.0.3 - minimalistic-assert: ^1.0.1 - checksum: e350096e659c62422b85fa508e4b3669017311aa4c49b74f19f8e1bc7f3a54a584fdfd45326d4964d6011f2b2d882e38bea775a96046f2a61b7779a979629d8f - languageName: node - linkType: hard - "hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -6795,17 +6276,6 @@ __metadata: languageName: node linkType: hard -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: ^1.0.3 - minimalistic-assert: ^1.0.0 - minimalistic-crypto-utils: ^1.0.1 - checksum: bd30b6a68d7f22d63f10e1888aee497d7c2c5c0bb469e66bbdac99f143904d1dfe95f8131f95b3e86c86dd239963c9d972fcbe147e7cffa00e55d18585c43fe0 - languageName: node - linkType: hard - "hosted-git-info@npm:^2.1.4": version: 2.8.9 resolution: "hosted-git-info@npm:2.8.9" @@ -6813,15 +6283,6 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^3.0.0": - version: 3.0.0 - resolution: "html-encoding-sniffer@npm:3.0.0" - dependencies: - whatwg-encoding: ^2.0.0 - checksum: 8d806aa00487e279e5ccb573366a951a9f68f65c90298eac9c3a2b440a7ffe46615aff2995a2f61c6746c639234e6179a97e18ca5ccbbf93d3725ef2099a4502 - languageName: node - linkType: hard - "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -6836,19 +6297,6 @@ __metadata: languageName: node linkType: hard -"http-errors@npm:2.0.0": - version: 2.0.0 - resolution: "http-errors@npm:2.0.0" - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 - languageName: node - linkType: hard - "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -6860,25 +6308,7 @@ __metadata: languageName: node linkType: hard -"http-proxy@npm:^1.18.1": - version: 1.18.1 - resolution: "http-proxy@npm:1.18.1" - dependencies: - eventemitter3: ^4.0.0 - follow-redirects: ^1.0.0 - requires-port: ^1.0.0 - checksum: f5bd96bf83e0b1e4226633dbb51f8b056c3e6321917df402deacec31dd7fe433914fc7a2c1831cf7ae21e69c90b3a669b8f434723e9e8b71fd68afe30737b6a5 - languageName: node - linkType: hard - -"https-browserify@npm:^1.0.0": - version: 1.0.0 - resolution: "https-browserify@npm:1.0.0" - checksum: 09b35353e42069fde2435760d13f8a3fb7dd9105e358270e2e225b8a94f811b461edd17cb57594e5f36ec1218f121c160ddceeec6e8be2d55e01dcbbbed8cbae - languageName: node - linkType: hard - -"https-proxy-agent@npm:5.0.1, https-proxy-agent@npm:^5.0.0, https-proxy-agent@npm:^5.0.1": +"https-proxy-agent@npm:5.0.1, https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -6932,7 +6362,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": +"iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -6941,7 +6371,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": +"iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -7031,22 +6461,13 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 languageName: node linkType: hard -"inline-source-map@npm:~0.6.0": - version: 0.6.2 - resolution: "inline-source-map@npm:0.6.2" - dependencies: - source-map: ~0.5.3 - checksum: 1f7fa2ad1764d03a0a525d5c47993f9e3d0445f29c2e2413d2878deecb6ecb1e6f9137a6207e3db8dc129565bde15de88c1ba2665407e753e7f3ec768ca29262 - languageName: node - linkType: hard - "internal-slot@npm:^1.0.7": version: 1.0.7 resolution: "internal-slot@npm:1.0.7" @@ -7072,16 +6493,6 @@ __metadata: languageName: node linkType: hard -"is-arguments@npm:^1.0.4": - version: 1.1.1 - resolution: "is-arguments@npm:1.1.1" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 - languageName: node - linkType: hard - "is-array-buffer@npm:^3.0.4": version: 3.0.4 resolution: "is-array-buffer@npm:3.0.4" @@ -7108,15 +6519,6 @@ __metadata: languageName: node linkType: hard -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: ^2.0.0 - checksum: 84192eb88cff70d320426f35ecd63c3d6d495da9d805b19bc65b518984b7c0760280e57dbf119b7e9be6b161784a5a673ab2c6abe83abb5198a432232ad5b35c - languageName: node - linkType: hard - "is-boolean-object@npm:^1.1.0": version: 1.1.2 resolution: "is-boolean-object@npm:1.1.2" @@ -7188,15 +6590,6 @@ __metadata: languageName: node linkType: hard -"is-docker@npm:^2.0.0": - version: 2.2.1 - resolution: "is-docker@npm:2.2.1" - bin: - is-docker: cli.js - checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 - languageName: node - linkType: hard - "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -7218,16 +6611,7 @@ __metadata: languageName: node linkType: hard -"is-generator-function@npm:^1.0.7": - version: 1.0.10 - resolution: "is-generator-function@npm:1.0.10" - dependencies: - has-tostringtag: ^1.0.0 - checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -7243,16 +6627,6 @@ __metadata: languageName: node linkType: hard -"is-nan@npm:^1.2.1": - version: 1.3.2 - resolution: "is-nan@npm:1.3.2" - dependencies: - call-bind: ^1.0.0 - define-properties: ^1.1.3 - checksum: 5dfadcef6ad12d3029d43643d9800adbba21cf3ce2ec849f734b0e14ee8da4070d82b15fdb35138716d02587c6578225b9a22779cab34888a139cc43e4e3610a - languageName: node - linkType: hard - "is-negative-zero@npm:^2.0.3": version: 2.0.3 resolution: "is-negative-zero@npm:2.0.3" @@ -7290,13 +6664,6 @@ __metadata: languageName: node linkType: hard -"is-potential-custom-element-name@npm:^1.0.1": - version: 1.0.1 - resolution: "is-potential-custom-element-name@npm:1.0.1" - checksum: ced7bbbb6433a5b684af581872afe0e1767e2d1146b2207ca0068a648fb5cab9d898495d1ac0583524faaf24ca98176a7d9876363097c2d14fee6dd324f3a1ab - languageName: node - linkType: hard - "is-regex@npm:^1.1.4": version: 1.1.4 resolution: "is-regex@npm:1.1.4" @@ -7350,19 +6717,6 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.3": - version: 1.1.10 - resolution: "is-typed-array@npm:1.1.10" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: aac6ecb59d4c56a1cdeb69b1f129154ef462bbffe434cb8a8235ca89b42f258b7ae94073c41b3cb7bce37f6a1733ad4499f07882d5d5093a7ba84dfc4ebb8017 - languageName: node - linkType: hard - "is-typed-array@npm:^1.1.13": version: 1.1.13 resolution: "is-typed-array@npm:1.1.13" @@ -7388,15 +6742,6 @@ __metadata: languageName: node linkType: hard -"is-wsl@npm:^2.2.0": - version: 2.2.0 - resolution: "is-wsl@npm:2.2.0" - dependencies: - is-docker: ^2.0.0 - checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 - languageName: node - linkType: hard - "isarray@npm:^2.0.5": version: 2.0.5 resolution: "isarray@npm:2.0.5" @@ -7404,13 +6749,6 @@ __metadata: languageName: node linkType: hard -"isbinaryfile@npm:^4.0.8": - version: 4.0.10 - resolution: "isbinaryfile@npm:4.0.10" - checksum: a6b28db7e23ac7a77d3707567cac81356ea18bd602a4f21f424f862a31d0e7ab4f250759c98a559ece35ffe4d99f0d339f1ab884ffa9795172f632ab8f88e686 - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -7425,18 +6763,6 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^4.0.0": - version: 4.0.3 - resolution: "istanbul-lib-instrument@npm:4.0.3" - dependencies: - "@babel/core": ^7.7.5 - "@istanbuljs/schema": ^0.1.2 - istanbul-lib-coverage: ^3.0.0 - semver: ^6.3.0 - checksum: fa1171d3022b1bb8f6a734042620ac5d9ee7dc80f3065a0bb12863e9f0494d0eefa3d86608fcc0254ab2765d29d7dad8bdc42e5f8df2f9a1fbe85ccc59d76cb9 - languageName: node - linkType: hard - "istanbul-lib-instrument@npm:^5.0.4": version: 5.2.1 resolution: "istanbul-lib-instrument@npm:5.2.1" @@ -7485,7 +6811,7 @@ __metadata: languageName: node linkType: hard -"istanbul-reports@npm:^3.0.0, istanbul-reports@npm:^3.1.3": +"istanbul-reports@npm:^3.1.3": version: 3.1.5 resolution: "istanbul-reports@npm:3.1.5" dependencies: @@ -7495,13 +6821,6 @@ __metadata: languageName: node linkType: hard -"jasmine-core@npm:^4.1.0": - version: 4.6.0 - resolution: "jasmine-core@npm:4.6.0" - checksum: c5c5ce16c512cf0bc8b6b4f2d4f0ac7b23cae90624e0cd9d22da3baab3266e9a4da5a9363fb7937b16e0a4cf550bb79183cd74483ce55cfff4b6678434d599b7 - languageName: node - linkType: hard - "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -7651,27 +6970,6 @@ __metadata: languageName: node linkType: hard -"jest-environment-jsdom@npm:29.7.0": - version: 29.7.0 - resolution: "jest-environment-jsdom@npm:29.7.0" - dependencies: - "@jest/environment": ^29.7.0 - "@jest/fake-timers": ^29.7.0 - "@jest/types": ^29.6.3 - "@types/jsdom": ^20.0.0 - "@types/node": "*" - jest-mock: ^29.7.0 - jest-util: ^29.7.0 - jsdom: ^20.0.0 - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 559aac134c196fccc1dfc794d8fc87377e9f78e894bb13012b0831d88dec0abd7ece99abec69da564b8073803be4f04a9eb4f4d1bb80e29eec0cb252c254deb8 - languageName: node - linkType: hard - "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -8041,45 +7339,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^20.0.0": - version: 20.0.3 - resolution: "jsdom@npm:20.0.3" - dependencies: - abab: ^2.0.6 - acorn: ^8.8.1 - acorn-globals: ^7.0.0 - cssom: ^0.5.0 - cssstyle: ^2.3.0 - data-urls: ^3.0.2 - decimal.js: ^10.4.2 - domexception: ^4.0.0 - escodegen: ^2.0.0 - form-data: ^4.0.0 - html-encoding-sniffer: ^3.0.0 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.1 - is-potential-custom-element-name: ^1.0.1 - nwsapi: ^2.2.2 - parse5: ^7.1.1 - saxes: ^6.0.0 - symbol-tree: ^3.2.4 - tough-cookie: ^4.1.2 - w3c-xmlserializer: ^4.0.0 - webidl-conversions: ^7.0.0 - whatwg-encoding: ^2.0.0 - whatwg-mimetype: ^3.0.0 - whatwg-url: ^11.0.0 - ws: ^8.11.0 - xml-name-validator: ^4.0.0 - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 6e2ae21db397133a061b270c26d2dbc0b9051733ea3b896a7ece78d79f475ff0974f766a413c1198a79c793159119169f2335ddb23150348fbfdcfa6f3105536 - languageName: node - linkType: hard - "jsesc@npm:^2.5.1": version: 2.5.2 resolution: "jsesc@npm:2.5.2" @@ -8119,169 +7378,31 @@ __metadata: languageName: node linkType: hard -"json-stringify-safe@npm:^5.0.1": - version: 5.0.1 - resolution: "json-stringify-safe@npm:5.0.1" - checksum: 48ec0adad5280b8a96bb93f4563aa1667fd7a36334f79149abd42446d0989f2ddc58274b479f4819f1f00617957e6344c886c55d05a4e15ebb4ab931e4a6a8ee - languageName: node - linkType: hard - -"json5@npm:^2.2.2, json5@npm:^2.2.3": - version: 2.2.3 - resolution: "json5@npm:2.2.3" - bin: - json5: lib/cli.js - checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 - languageName: node - linkType: hard - -"jsonc-parser@npm:^3.0.0": - version: 3.2.0 - resolution: "jsonc-parser@npm:3.2.0" - checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 - languageName: node - linkType: hard - -"jsonfile@npm:^4.0.0": - version: 4.0.0 - resolution: "jsonfile@npm:4.0.0" - dependencies: - graceful-fs: ^4.1.6 - dependenciesMeta: - graceful-fs: - optional: true - checksum: 6447d6224f0d31623eef9b51185af03ac328a7553efcee30fa423d98a9e276ca08db87d71e17f2310b0263fd3ffa6c2a90a6308367f661dc21580f9469897c9e - languageName: node - linkType: hard - -"karma-chrome-launcher@npm:3.2.0": - version: 3.2.0 - resolution: "karma-chrome-launcher@npm:3.2.0" - dependencies: - which: ^1.2.1 - checksum: e1119e4f95dbcdaec937e5d15a9ffea1b7e5c1d7566f7074ff140161983d4a0821ad274d3dcc34aacfb792caf842a39c459ba9c263723faa6a060cca8692d9b7 - languageName: node - linkType: hard - -"karma-firefox-launcher@npm:2.1.3": - version: 2.1.3 - resolution: "karma-firefox-launcher@npm:2.1.3" - dependencies: - is-wsl: ^2.2.0 - which: ^3.0.0 - checksum: 35a82b1e5c013cbc83aed0d58d2d4e2d71d4246ff89ced5c9474ebceaef299f7daff0bf86c052f4cfb6497d76e0fde7f23db2735e6766e8df831030d8babb4db - languageName: node - linkType: hard - -"karma-jasmine@npm:5.1.0": - version: 5.1.0 - resolution: "karma-jasmine@npm:5.1.0" - dependencies: - jasmine-core: ^4.1.0 - peerDependencies: - karma: ^6.0.0 - checksum: ebefd1094e7c2b4c854027621d854908166c79cccaabb5a6ba0ace42cd785a9da0a9aad1aa41937956bd4848287eac04886eebfd7c851b927d2132d3563b7739 - languageName: node - linkType: hard - -"karma-typescript@npm:5.5.4": - version: 5.5.4 - resolution: "karma-typescript@npm:5.5.4" - dependencies: - acorn: ^8.1.0 - acorn-walk: ^8.0.2 - assert: ^2.0.0 - async: ^3.0.1 - browser-resolve: ^2.0.0 - browserify-zlib: ^0.2.0 - buffer: ^5.4.3 - combine-source-map: ^0.8.0 - console-browserify: ^1.2.0 - constants-browserify: ^1.0.0 - convert-source-map: ^1.7.0 - crypto-browserify: ^3.12.0 - diff: ^4.0.1 - domain-browser: ^4.16.0 - events: ^3.2.0 - glob: ^7.1.6 - https-browserify: ^1.0.0 - istanbul-lib-coverage: ^3.0.0 - istanbul-lib-instrument: ^4.0.0 - istanbul-lib-report: ^3.0.0 - istanbul-lib-source-maps: ^4.0.0 - istanbul-reports: ^3.0.0 - json-stringify-safe: ^5.0.1 - lodash: ^4.17.19 - log4js: ^6.3.0 - minimatch: ^3.0.4 - os-browserify: ^0.3.0 - pad: ^3.2.0 - path-browserify: ^1.0.0 - process: ^0.11.10 - punycode: ^2.1.1 - querystring-es3: ^0.2.1 - readable-stream: ^3.1.1 - source-map: ^0.7.3 - stream-browserify: ^3.0.0 - stream-http: ^3.1.0 - string_decoder: ^1.3.0 - timers-browserify: ^2.0.11 - tmp: ^0.2.1 - tty-browserify: ^0.0.1 - url: ^0.11.0 - util: ^0.12.1 - vm-browserify: ^1.1.2 - peerDependencies: - karma: 1 || 2 || 3 || 4 || 5 || 6 - typescript: 1 || 2 || 3 || 4 || 5 - checksum: 81336ac06ef1c292285212c8d7299e75a6f8905de6cfb2193611f8f996f633d3380df3e90dd5c8925f1d03caba49fc525a62150f0a34d9a70312664a3ac3a846 +"json5@npm:^2.2.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 languageName: node linkType: hard -"karma-webpack@npm:5.0.1": - version: 5.0.1 - resolution: "karma-webpack@npm:5.0.1" - dependencies: - glob: ^7.1.3 - minimatch: ^9.0.3 - webpack-merge: ^4.1.5 - peerDependencies: - webpack: ^5.0.0 - checksum: c0faa2cc151ee81a1fb0057c84c3c4a367735ffbba8bd5561c1a539c0880bbc47cf04358ca70f366ca22aaf13fe00fcd4bba4dbbcaa06f4396e1a5f0ca122d10 +"jsonc-parser@npm:^3.0.0": + version: 3.2.0 + resolution: "jsonc-parser@npm:3.2.0" + checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 languageName: node linkType: hard -"karma@npm:6.4.3": - version: 6.4.3 - resolution: "karma@npm:6.4.3" +"jsonfile@npm:^4.0.0": + version: 4.0.0 + resolution: "jsonfile@npm:4.0.0" 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.7.2 - source-map: ^0.6.1 - tmp: ^0.2.1 - ua-parser-js: ^0.7.30 - yargs: ^16.1.1 - bin: - karma: bin/karma - checksum: 4eee6f52c7cf54d860bb35600b61eac3631647efa01282671c9f799dbe4ea80ac729946c8c82e53be778905b5920d221b527c86bd9bec73214ca2f84339aebbe + graceful-fs: ^4.1.6 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 6447d6224f0d31623eef9b51185af03ac328a7553efcee30fa423d98a9e276ca08db87d71e17f2310b0263fd3ffa6c2a90a6308367f661dc21580f9469897c9e languageName: node linkType: hard @@ -8323,16 +7444,6 @@ __metadata: languageName: node linkType: hard -"levn@npm:~0.3.0": - version: 0.3.0 - resolution: "levn@npm:0.3.0" - dependencies: - prelude-ls: ~1.1.2 - type-check: ~0.3.2 - checksum: 0d084a524231a8246bb10fec48cdbb35282099f6954838604f3c7fc66f2e16fa66fd9cc2f3f20a541a113c4dafdf181e822c887c8a319c9195444e6c64ac395e - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -8359,6 +7470,13 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^0.4.3": + version: 0.4.3 + resolution: "local-pkg@npm:0.4.3" + checksum: 7825aca531dd6afa3a3712a0208697aa4a5cd009065f32e3fb732aafcc42ed11f277b5ac67229222e96f4def55197171cdf3d5522d0381b489d2e5547b407d55 + languageName: node + linkType: hard + "locate-path@npm:^5.0.0": version: 5.0.0 resolution: "locate-path@npm:5.0.0" @@ -8398,13 +7516,6 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:~3.0.3": - version: 3.0.4 - resolution: "lodash.memoize@npm:3.0.4" - checksum: fc52e0916b896fa79d6b85fbeaa0e44a381b70f1fcab7acab10188aaeeb2107e21b9b992bff560f405696e0a6e3bb5c08af18955d628a1e8ab6b11df14ff6172 - languageName: node - linkType: hard - "lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" @@ -8419,23 +7530,19 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21, lodash@npm:~4.17.15": +"lodash@npm:^4.17.21, lodash@npm:~4.17.15": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 languageName: node linkType: hard -"log4js@npm:^6.3.0, log4js@npm:^6.4.1": - version: 6.9.1 - resolution: "log4js@npm:6.9.1" +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" dependencies: - date-format: ^4.0.14 - debug: ^4.3.4 - flatted: ^3.2.7 - rfdc: ^1.3.0 - streamroller: ^3.1.5 - checksum: 59d98c37d4163138dab5d9b06ae26965d1353106fece143973d57b1003b3a482791aa21374fd2cca81a953b8837b2f9756ac225404e60cbfa4dd3ab59f082e2e + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b languageName: node linkType: hard @@ -8481,6 +7588,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.1": + version: 0.30.12 + resolution: "magic-string@npm:0.30.12" + dependencies: + "@jridgewell/sourcemap-codec": ^1.5.0 + checksum: 3f0d23b74371765f0e6cad4284eebba0ac029c7a55e39292de5aa92281afb827138cb2323d24d2924f6b31f138c3783596c5ccaa98653fe9cf122e1f81325b59 + languageName: node + linkType: hard + "make-dir@npm:^3.0.0": version: 3.1.0 resolution: "make-dir@npm:3.1.0" @@ -8553,24 +7669,6 @@ __metadata: languageName: node linkType: hard -"md5.js@npm:^1.3.4": - version: 1.3.5 - resolution: "md5.js@npm:1.3.5" - dependencies: - hash-base: ^3.0.0 - inherits: ^2.0.1 - safe-buffer: ^5.1.2 - checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c - languageName: node - linkType: hard - -"media-typer@npm:0.3.0": - version: 0.3.0 - resolution: "media-typer@npm:0.3.0" - checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 - languageName: node - linkType: hard - "meow@npm:^6.0.0": version: 6.1.1 resolution: "meow@npm:6.1.1" @@ -8624,18 +7722,6 @@ __metadata: languageName: node linkType: hard -"miller-rabin@npm:^4.0.0": - version: 4.0.1 - resolution: "miller-rabin@npm:4.0.1" - dependencies: - bn.js: ^4.0.0 - brorand: ^1.0.1 - bin: - miller-rabin: bin/miller-rabin - checksum: 00cd1ab838ac49b03f236cc32a14d29d7d28637a53096bf5c6246a032a37749c9bd9ce7360cbf55b41b89b7d649824949ff12bc8eee29ac77c6b38eada619ece - languageName: node - linkType: hard - "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -8643,7 +7729,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.27": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -8652,15 +7738,6 @@ __metadata: languageName: node linkType: hard -"mime@npm:^2.5.2": - version: 2.6.0 - resolution: "mime@npm:2.6.0" - bin: - mime: cli.js - checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 - languageName: node - linkType: hard - "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -8675,20 +7752,6 @@ __metadata: languageName: node linkType: hard -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-assert@npm:1.0.1" - checksum: cc7974a9268fbf130fb055aff76700d7e2d8be5f761fb5c60318d0ed010d839ab3661a533ad29a5d37653133385204c503bfac995aaa4236f4e847461ea32ba7 - languageName: node - linkType: hard - -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 6e8a0422b30039406efd4c440829ea8f988845db02a3299f372fceba56ffa94994a9c0f2fd70c17f9969eedfbd72f34b5070ead9656a34d3f71c0bd72583a0ed - languageName: node - linkType: hard - "minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -8707,7 +7770,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.4": version: 9.0.4 resolution: "minimatch@npm:9.0.4" dependencies: @@ -8727,13 +7790,6 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.6": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 - languageName: node - linkType: hard - "minipass-collect@npm:^1.0.2": version: 1.0.2 resolution: "minipass-collect@npm:1.0.2" @@ -8832,17 +7888,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^0.5.5": - version: 0.5.6 - resolution: "mkdirp@npm:0.5.6" - dependencies: - minimist: ^1.2.6 - bin: - mkdirp: bin/cmd.js - checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 - languageName: node - linkType: hard - "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -8852,10 +7897,15 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.0.0": - version: 2.0.0 - resolution: "ms@npm:2.0.0" - checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 +"mlly@npm:^1.4.0, mlly@npm:^1.7.2": + version: 1.7.2 + resolution: "mlly@npm:1.7.2" + dependencies: + acorn: ^8.12.1 + pathe: ^1.1.2 + pkg-types: ^1.2.0 + ufo: ^1.5.4 + checksum: 66a92b0ac4f76cac22d2d6688338fece01f2ac4afd7816cd4224525c1f9032c452075730c54c3ef7558485455d704b7141060e517785c93b276b2faa3bb04199 languageName: node linkType: hard @@ -8873,6 +7923,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -8880,7 +7939,7 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": +"negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 @@ -8894,18 +7953,6 @@ __metadata: languageName: node linkType: hard -"nock@npm:^13.0.2": - version: 13.3.1 - resolution: "nock@npm:13.3.1" - dependencies: - debug: ^4.1.0 - json-stringify-safe: ^5.0.1 - lodash: ^4.17.21 - propagate: ^2.0.0 - checksum: 0f2a73e8432f6b5650656c53eef99f9e5bbde3df538dc2f07057edc4438cfc61a394c9d06dd82e60f6e86d42433f20f3c04364a1f088beee7bf03a24e3f0fdd0 - languageName: node - linkType: hard - "node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -8984,7 +8031,7 @@ __metadata: languageName: node linkType: hard -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": +"normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 @@ -9012,20 +8059,6 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.2": - version: 2.2.9 - resolution: "nwsapi@npm:2.2.9" - checksum: 3ab2bc47d5507a76e2fdee5aae7ea2875c6def912d0401126cad3e39825a7decb7a02622810c855a7902bd31e917e606b37882dca12b0ae54b4d3b70275de927 - languageName: node - linkType: hard - -"object-assign@npm:^4": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - "object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" @@ -9040,16 +8073,6 @@ __metadata: languageName: node linkType: hard -"object-is@npm:^1.0.1": - version: 1.1.5 - resolution: "object-is@npm:1.1.5" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe - languageName: node - linkType: hard - "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -9069,24 +8092,6 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:2.4.1": - version: 2.4.1 - resolution: "on-finished@npm:2.4.1" - dependencies: - ee-first: 1.1.1 - checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 - languageName: node - linkType: hard - -"on-finished@npm:~2.3.0": - version: 2.3.0 - resolution: "on-finished@npm:2.3.0" - dependencies: - ee-first: 1.1.1 - checksum: 1db595bd963b0124d6fa261d18320422407b8f01dc65863840f3ddaaf7bcad5b28ff6847286703ca53f4ec19595bd67a2f1253db79fc4094911ec6aa8df1671b - languageName: node - linkType: hard - "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -9114,20 +8119,6 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.8.1": - version: 0.8.3 - resolution: "optionator@npm:0.8.3" - dependencies: - deep-is: ~0.1.3 - fast-levenshtein: ~2.0.6 - levn: ~0.3.0 - prelude-ls: ~1.1.2 - type-check: ~0.3.2 - word-wrap: ~1.2.3 - checksum: b8695ddf3d593203e25ab0900e265d860038486c943ff8b774f596a310f8ceebdb30c6832407a8198ba3ec9debe1abe1f51d4aad94843612db3b76d690c61d34 - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -9142,13 +8133,6 @@ __metadata: languageName: node linkType: hard -"os-browserify@npm:^0.3.0": - version: 0.3.0 - resolution: "os-browserify@npm:0.3.0" - checksum: 16e37ba3c0e6a4c63443c7b55799ce4066d59104143cb637ecb9fce586d5da319cdca786ba1c867abbe3890d2cbf37953f2d51eea85e20dd6c4570d6c54bfebf - languageName: node - linkType: hard - "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -9190,6 +8174,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: ^1.0.0 + checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b + languageName: node + linkType: hard + "p-locate@npm:^4.1.0": version: 4.1.0 resolution: "p-locate@npm:4.1.0" @@ -9231,22 +8224,6 @@ __metadata: languageName: node linkType: hard -"pad@npm:^3.2.0": - version: 3.2.0 - resolution: "pad@npm:3.2.0" - dependencies: - wcwidth: ^1.0.1 - checksum: c681c974613c3681058344d56090883260ba82401e507f11a21676a5cd5e4a9364b24fcaf9063d402311b7a8f1c38563a38c986b390595337f66c278a1d96698 - languageName: node - linkType: hard - -"pako@npm:~1.0.5": - version: 1.0.11 - resolution: "pako@npm:1.0.11" - checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -9256,19 +8233,6 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": - version: 5.1.6 - resolution: "parse-asn1@npm:5.1.6" - dependencies: - asn1.js: ^5.2.0 - browserify-aes: ^1.0.0 - evp_bytestokey: ^1.0.0 - pbkdf2: ^3.0.3 - safe-buffer: ^5.1.1 - checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 - languageName: node - linkType: hard - "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -9281,26 +8245,12 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0, parse5@npm:^7.1.1": - version: 7.1.2 - resolution: "parse5@npm:7.1.2" +"parse5@npm:^7.0.0": + version: 7.2.1 + resolution: "parse5@npm:7.2.1" dependencies: - entities: ^4.4.0 - checksum: 59465dd05eb4c5ec87b76173d1c596e152a10e290b7abcda1aecf0f33be49646ea74840c69af975d7887543ea45564801736356c568d6b5e71792fd0f4055713 - languageName: node - linkType: hard - -"parseurl@npm:~1.3.3": - version: 1.3.3 - resolution: "parseurl@npm:1.3.3" - checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 - languageName: node - linkType: hard - -"path-browserify@npm:^1.0.0": - version: 1.0.1 - resolution: "path-browserify@npm:1.0.1" - checksum: c6d7fa376423fe35b95b2d67990060c3ee304fc815ff0a2dc1c6c3cfaff2bd0d572ee67e18f19d0ea3bbe32e8add2a05021132ac40509416459fffee35200699 + entities: ^4.5.0 + checksum: 11253cf8aa2e7fc41c004c64cba6f2c255f809663365db65bd7ad0e8cf7b89e436a563c20059346371cc543a6c1b567032088883ca6a2cbc88276c666b68236d languageName: node linkType: hard @@ -9339,16 +8289,17 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.3": - version: 3.1.2 - resolution: "pbkdf2@npm:3.1.2" - dependencies: - create-hash: ^1.1.2 - create-hmac: ^1.1.4 - ripemd160: ^2.0.1 - safe-buffer: ^5.0.1 - sha.js: ^2.4.8 - checksum: 2c950a100b1da72123449208e231afc188d980177d021d7121e96a2de7f2abbc96ead2b87d03d8fe5c318face097f203270d7e27908af9f471c165a4e8e69c92 +"pathe@npm:^1.1.1, pathe@npm:^1.1.2": + version: 1.1.2 + resolution: "pathe@npm:1.1.2" + checksum: ec5f778d9790e7b9ffc3e4c1df39a5bb1ce94657a4e3ad830c1276491ca9d79f189f47609884671db173400256b005f4955f7952f52a2aeb5834ad5fb4faf134 + languageName: node + linkType: hard + +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 languageName: node linkType: hard @@ -9366,7 +8317,14 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": +"picocolors@npm:^1.1.0": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf @@ -9405,6 +8363,17 @@ __metadata: languageName: node linkType: hard +"pkg-types@npm:^1.2.0": + version: 1.2.1 + resolution: "pkg-types@npm:1.2.1" + dependencies: + confbox: ^0.1.8 + mlly: ^1.7.2 + pathe: ^1.1.2 + checksum: d2e3ad7aef36cc92b17403e61c04db521bf0beb175ccb4d432c284239f00ec32ff37feb072a260613e9ff727911cff1127a083fd52f91b9bec6b62970f385702 + languageName: node + linkType: hard + "please-upgrade-node@npm:^3.2.0": version: 3.2.0 resolution: "please-upgrade-node@npm:3.2.0" @@ -9421,6 +8390,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.27": + version: 8.4.47 + resolution: "postcss@npm:8.4.47" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.1.0 + source-map-js: ^1.2.1 + checksum: f78440a9d8f97431dd2ab1ab8e1de64f12f3eff38a3d8d4a33919b96c381046a314658d2de213a5fa5eb296b656de76a3ec269fdea27f16d5ab465b916a0f52c + languageName: node + linkType: hard + "preferred-pm@npm:^3.0.0": version: 3.1.3 resolution: "preferred-pm@npm:3.1.3" @@ -9440,13 +8420,6 @@ __metadata: languageName: node linkType: hard -"prelude-ls@npm:~1.1.2": - version: 1.1.2 - resolution: "prelude-ls@npm:1.1.2" - checksum: c4867c87488e4a0c233e158e4d0d5565b609b105d75e4c05dc760840475f06b731332eb93cc8c9cecb840aa8ec323ca3c9a56ad7820ad2e63f0261dadcb154e4 - languageName: node - linkType: hard - "prettier@npm:3.2.5": version: 3.2.5 resolution: "prettier@npm:3.2.5" @@ -9477,7 +8450,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.7.0": +"pretty-format@npm:^29.5.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" dependencies: @@ -9488,13 +8461,6 @@ __metadata: languageName: node linkType: hard -"process@npm:^0.11.10": - version: 0.11.10 - resolution: "process@npm:0.11.10" - checksum: bfcce49814f7d172a6e6a14d5fa3ac92cc3d0c3b9feb1279774708a719e19acd673995226351a082a9ae99978254e320ccda4240ddc474ba31a76c79491ca7c3 - languageName: node - linkType: hard - "progress@npm:2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" @@ -9529,13 +8495,6 @@ __metadata: languageName: node linkType: hard -"propagate@npm:^2.0.0": - version: 2.0.1 - resolution: "propagate@npm:2.0.1" - checksum: c4febaee2be0979e82fb6b3727878fd122a98d64a7fa3c9d09b0576751b88514a9e9275b1b92e76b364d488f508e223bd7e1dcdc616be4cdda876072fbc2a96c - languageName: node - linkType: hard - "proxy-from-env@npm:1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" @@ -9550,27 +8509,6 @@ __metadata: languageName: node linkType: hard -"psl@npm:^1.1.33": - version: 1.9.0 - resolution: "psl@npm:1.9.0" - checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d - languageName: node - linkType: hard - -"public-encrypt@npm:^4.0.0": - version: 4.0.3 - resolution: "public-encrypt@npm:4.0.3" - dependencies: - bn.js: ^4.1.0 - browserify-rsa: ^4.0.0 - create-hash: ^1.1.0 - parse-asn1: ^5.0.0 - randombytes: ^2.0.1 - safe-buffer: ^5.1.2 - checksum: 215d446e43cef021a20b67c1df455e5eea134af0b1f9b8a35f9e850abf32991b0c307327bc5b9bc07162c288d5cdb3d4a783ea6c6640979ed7b5017e3e0c9935 - languageName: node - linkType: hard - "pump@npm:^3.0.0": version: 3.0.0 resolution: "pump@npm:3.0.0" @@ -9581,14 +8519,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^1.4.1": - version: 1.4.1 - resolution: "punycode@npm:1.4.1" - checksum: fa6e698cb53db45e4628559e557ddaf554103d2a96a1d62892c8f4032cd3bc8871796cae9eabc1bc700e2b6677611521ce5bb1d9a27700086039965d0cf34518 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0, punycode@npm:^2.1.1": +"punycode@npm:^2.1.0": version: 2.3.0 resolution: "punycode@npm:2.3.0" checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 @@ -9640,45 +8571,6 @@ __metadata: languageName: node linkType: hard -"qjobs@npm:^1.2.0": - version: 1.2.0 - resolution: "qjobs@npm:1.2.0" - checksum: eb64c00724d2fecaf9246383b4eebc3a4c34845b25d41921dd57f41b30a4310cef661543facac27ceb6911aab64a1acdf45b5d8f1d5e2838554d0c010ee56852 - languageName: node - linkType: hard - -"qs@npm:6.11.0": - version: 6.11.0 - resolution: "qs@npm:6.11.0" - dependencies: - side-channel: ^1.0.4 - checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 - languageName: node - linkType: hard - -"qs@npm:^6.11.0": - version: 6.11.2 - resolution: "qs@npm:6.11.2" - dependencies: - side-channel: ^1.0.4 - checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b - languageName: node - linkType: hard - -"querystring-es3@npm:^0.2.1": - version: 0.2.1 - resolution: "querystring-es3@npm:0.2.1" - checksum: 691e8d6b8b157e7cd49ae8e83fcf86de39ab3ba948c25abaa94fba84c0986c641aa2f597770848c64abce290ed17a39c9df6df737dfa7e87c3b63acc7d225d61 - languageName: node - linkType: hard - -"querystringify@npm:^2.1.1": - version: 2.2.0 - resolution: "querystringify@npm:2.2.0" - checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 - languageName: node - linkType: hard - "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -9693,7 +8585,7 @@ __metadata: languageName: node linkType: hard -"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": +"randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" dependencies: @@ -9702,35 +8594,6 @@ __metadata: languageName: node linkType: hard -"randomfill@npm:^1.0.3": - version: 1.0.4 - resolution: "randomfill@npm:1.0.4" - dependencies: - randombytes: ^2.0.5 - safe-buffer: ^5.1.0 - checksum: 33734bb578a868d29ee1b8555e21a36711db084065d94e019a6d03caa67debef8d6a1bfd06a2b597e32901ddc761ab483a85393f0d9a75838f1912461d4dbfc7 - languageName: node - linkType: hard - -"range-parser@npm:^1.2.1": - version: 1.2.1 - resolution: "range-parser@npm:1.2.1" - checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 - languageName: node - linkType: hard - -"raw-body@npm:2.5.2": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 - languageName: node - linkType: hard - "re2-wasm@npm:^1.0.2": version: 1.0.2 resolution: "re2-wasm@npm:1.0.2" @@ -9780,7 +8643,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.2": +"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -9802,15 +8665,6 @@ __metadata: languageName: node linkType: hard -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: ^2.2.1 - checksum: 1ced032e6e45670b6d7352d71d21ce7edf7b9b928494dcaba6f11fba63180d9da6cd7061ebc34175ffda6ff529f481818c962952004d273178acd70f7059b320 - languageName: node - linkType: hard - "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" @@ -9863,13 +8717,6 @@ __metadata: languageName: node linkType: hard -"requires-port@npm:^1.0.0": - version: 1.0.0 - resolution: "requires-port@npm:1.0.0" - checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff - languageName: node - linkType: hard - "resolve-cwd@npm:^3.0.0": version: 3.0.0 resolution: "resolve-cwd@npm:3.0.0" @@ -9926,7 +8773,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.17.0, resolve@npm:^1.20.0, resolve@npm:~1.22.1": +"resolve@npm:^1.20.0, resolve@npm:~1.22.1": version: 1.22.3 resolution: "resolve@npm:1.22.3" dependencies: @@ -9975,7 +8822,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.3 resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=c3c19d" dependencies: @@ -10012,13 +8859,6 @@ __metadata: languageName: node linkType: hard -"rfdc@npm:^1.3.0": - version: 1.3.0 - resolution: "rfdc@npm:1.3.0" - checksum: fb2ba8512e43519983b4c61bd3fa77c0f410eff6bae68b08614437bc3f35f91362215f7b4a73cbda6f67330b5746ce07db5dd9850ad3edc91271ad6deea0df32 - languageName: node - linkType: hard - "rimraf@npm:3.0.2, rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" @@ -10030,13 +8870,17 @@ __metadata: languageName: node linkType: hard -"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": - version: 2.0.2 - resolution: "ripemd160@npm:2.0.2" +"rollup@npm:^3.27.1": + version: 3.29.5 + resolution: "rollup@npm:3.29.5" dependencies: - hash-base: ^3.0.0 - inherits: ^2.0.1 - checksum: 006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 + fsevents: ~2.3.2 + dependenciesMeta: + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 6f8304e58ac8170a715e61e46c4aa674b2ae2587ed2a712dab58f72e5e54803ae40b485fbe6b3e6a694f4c8f7a59ab936ccf9f6b686c7cfd1f1970fa9ecadf1a languageName: node linkType: hard @@ -10070,7 +8914,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -10088,19 +8932,10 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.1.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 - languageName: node - linkType: hard - -"saxes@npm:^6.0.0": - version: 6.0.0 - resolution: "saxes@npm:6.0.0" - dependencies: - xmlchars: ^2.2.0 - checksum: d3fa3e2aaf6c65ed52ee993aff1891fc47d5e47d515164b5449cbf5da2cbdc396137e55590472e64c5c436c14ae64a8a03c29b9e7389fc6f14035cf4e982ef3b + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 languageName: node linkType: hard @@ -10227,32 +9062,6 @@ __metadata: languageName: node linkType: hard -"setimmediate@npm:^1.0.4": - version: 1.0.5 - resolution: "setimmediate@npm:1.0.5" - checksum: c9a6f2c5b51a2dabdc0247db9c46460152ffc62ee139f3157440bd48e7c59425093f42719ac1d7931f054f153e2d26cf37dfeb8da17a794a58198a2705e527fd - languageName: node - linkType: hard - -"setprototypeof@npm:1.2.0": - version: 1.2.0 - resolution: "setprototypeof@npm:1.2.0" - checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 - languageName: node - linkType: hard - -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": - version: 2.4.11 - resolution: "sha.js@npm:2.4.11" - dependencies: - inherits: ^2.0.1 - safe-buffer: ^5.0.1 - bin: - sha.js: ./bin.js - checksum: ebd3f59d4b799000699097dadb831c8e3da3eb579144fd7eb7a19484cbcbb7aca3c68ba2bb362242eb09e33217de3b4ea56e4678184c334323eca24a58e3ad07 - languageName: node - linkType: hard - "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -10320,6 +9129,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -10372,67 +9188,31 @@ __metadata: "@microsoft/api-extractor": 7.34.4 "@tsconfig/recommended": 1.0.2 "@types/jest": 28.1.3 + "@types/jsdom": 20.0.1 "@typescript-eslint/eslint-plugin": 7.8.0 "@typescript-eslint/parser": 7.8.0 esbuild: 0.19.11 eslint: 8.57.0 eslint-plugin-simple-import-sort: 7.0.0 eslint-plugin-tsdoc: 0.2.17 + get-port: ^7.1.0 glob: ^7.1.6 + happy-dom: 14.12.3 husky: ^4.2.3 jest: 29.7.0 - jest-environment-jsdom: 29.7.0 - karma: 6.4.3 - karma-chrome-launcher: 3.2.0 - karma-firefox-launcher: 2.1.3 - karma-jasmine: 5.1.0 - karma-typescript: 5.5.4 - karma-webpack: 5.0.1 prettier: 3.2.5 puppeteer: ^19.2.0 rimraf: ^3.0.2 ts-jest: 29.1.2 turbo: latest typescript: ~5.2.2 + vite: 4.5.5 + vitest: 0.34.6 webpack: 5.91.0 yarn: 1.22.22 languageName: unknown linkType: soft -"socket.io-adapter@npm:~2.5.2": - version: 2.5.2 - resolution: "socket.io-adapter@npm:2.5.2" - dependencies: - ws: ~8.11.0 - checksum: 481251c3547221e57eb5cb247d0b1a3cde4d152a4c1c9051cc887345a7770e59f3b47f1011cac4499e833f01fcfc301ed13c4ec6e72f7dbb48a476375a6344cd - languageName: node - linkType: hard - -"socket.io-parser@npm:~4.2.4": - version: 4.2.4 - resolution: "socket.io-parser@npm:4.2.4" - dependencies: - "@socket.io/component-emitter": ~3.1.0 - debug: ~4.3.1 - checksum: 61540ef99af33e6a562b9effe0fad769bcb7ec6a301aba5a64b3a8bccb611a0abdbe25f469933ab80072582006a78ca136bf0ad8adff9c77c9953581285e2263 - languageName: node - linkType: hard - -"socket.io@npm:^4.7.2": - version: 4.7.5 - resolution: "socket.io@npm:4.7.5" - dependencies: - accepts: ~1.3.4 - base64id: ~2.0.0 - cors: ~2.8.5 - debug: ~4.3.2 - engine.io: ~6.5.2 - socket.io-adapter: ~2.5.2 - socket.io-parser: ~4.2.4 - checksum: b8b57216152cf230bdcb77b5450e124ebe1fee7482eeb50a6ef760b69f2f5a064e9b8640ce9c1efc5c9e081f5d797d3f6ff3f81606e19ddaf5d4114aad9ec7d3 - languageName: node - linkType: hard - "socks-proxy-agent@npm:^7.0.0": version: 7.0.0 resolution: "socks-proxy-agent@npm:7.0.0" @@ -10454,6 +9234,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b + languageName: node + linkType: hard + "source-map-support@npm:0.5.13": version: 0.5.13 resolution: "source-map-support@npm:0.5.13" @@ -10481,20 +9268,6 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.7.3": - version: 0.7.4 - resolution: "source-map@npm:0.7.4" - checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 - languageName: node - linkType: hard - -"source-map@npm:~0.5.3": - version: 0.5.7 - resolution: "source-map@npm:0.5.7" - checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d - languageName: node - linkType: hard - "spawn-command@npm:^0.0.2-1": version: 0.0.2 resolution: "spawn-command@npm:0.0.2" @@ -10571,39 +9344,17 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": - version: 2.0.1 - resolution: "statuses@npm:2.0.1" - checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb - languageName: node - linkType: hard - -"statuses@npm:~1.5.0": - version: 1.5.0 - resolution: "statuses@npm:1.5.0" - checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c - languageName: node - linkType: hard - -"stream-browserify@npm:^3.0.0": - version: 3.0.0 - resolution: "stream-browserify@npm:3.0.0" - dependencies: - inherits: ~2.0.4 - readable-stream: ^3.5.0 - checksum: 4c47ef64d6f03815a9ca3874e2319805e8e8a85f3550776c47ce523b6f4c6cd57f40e46ec6a9ab8ad260fde61863c2718f250d3bedb3fe9052444eb9abfd9921 +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 languageName: node linkType: hard -"stream-http@npm:^3.1.0": - version: 3.2.0 - resolution: "stream-http@npm:3.2.0" - dependencies: - builtin-status-codes: ^3.0.0 - inherits: ^2.0.4 - readable-stream: ^3.6.0 - xtend: ^4.0.2 - checksum: c9b78453aeb0c84fcc59555518ac62bacab9fa98e323e7b7666e5f9f58af8f3155e34481078509b02929bd1268427f664d186604cdccee95abc446099b339f83 +"std-env@npm:^3.3.3": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 4f489d13ff2ab838c9acd4ed6b786b51aa52ecacdfeaefe9275fcb220ff2ac80c6e95674723508fd29850a694569563a8caaaea738eb82ca16429b3a0b50e510 languageName: node linkType: hard @@ -10616,17 +9367,6 @@ __metadata: languageName: node linkType: hard -"streamroller@npm:^3.1.5": - version: 3.1.5 - resolution: "streamroller@npm:3.1.5" - dependencies: - date-format: ^4.0.14 - debug: ^4.3.4 - fs-extra: ^8.1.0 - checksum: c1df5612b785ffa4b6bbf16460590b62994c57265bc55a5166eebeeb0daf648e84bc52dc6d57e0cd4e5c7609bda93076753c63ff54589febd1e0b95590f0e443 - languageName: node - linkType: hard - "string-argv@npm:~0.3.1": version: 0.3.2 resolution: "string-argv@npm:0.3.2" @@ -10689,7 +9429,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": +"string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -10744,6 +9484,15 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^1.0.1": + version: 1.3.0 + resolution: "strip-literal@npm:1.3.0" + dependencies: + acorn: ^8.10.0 + checksum: f5fa7e289df8ebe82e90091fd393974faf8871be087ca50114327506519323cf15f2f8fee6ebe68b5e58bfc795269cae8bdc7cb5a83e27b02b3fe953f37b0a89 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -10778,13 +9527,6 @@ __metadata: languageName: node linkType: hard -"symbol-tree@npm:^3.2.4": - version: 3.2.4 - resolution: "symbol-tree@npm:3.2.4" - checksum: 6e8fc7e1486b8b54bea91199d9535bb72f10842e40c79e882fc94fb7b14b89866adf2fd79efa5ebb5b658bc07fb459ccce5ac0e99ef3d72f474e74aaf284029d - languageName: node - linkType: hard - "tapable@npm:^2.1.1, tapable@npm:^2.2.0": version: 2.2.1 resolution: "tapable@npm:2.2.1" @@ -10899,12 +9641,24 @@ __metadata: languageName: node linkType: hard -"timers-browserify@npm:^2.0.11": - version: 2.0.12 - resolution: "timers-browserify@npm:2.0.12" - dependencies: - setimmediate: ^1.0.4 - checksum: ec37ae299066bef6c464dcac29c7adafba1999e7227a9bdc4e105a459bee0f0b27234a46bfd7ab4041da79619e06a58433472867a913d01c26f8a203f87cee70 +"tinybench@npm:^2.5.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 1ab00d7dfe0d1f127cbf00822bacd9024f7a50a3ecd1f354a8168e0b7d2b53a639a24414e707c27879d1adc0f5153141d51d76ebd7b4d37fe245e742e5d91fe8 + languageName: node + linkType: hard + +"tinypool@npm:^0.7.0": + version: 0.7.0 + resolution: "tinypool@npm:0.7.0" + checksum: fdcccd5c750574fce51f8801a877f8284e145d12b79cd5f2d72bfbddfe20c895e915555bc848e122bb6aa968098e7ac4fe1e8e88104904d518dc01cccd18a510 + languageName: node + linkType: hard + +"tinyspy@npm:^2.1.1": + version: 2.2.1 + resolution: "tinyspy@npm:2.2.1" + checksum: 170d6232e87f9044f537b50b406a38fbfd6f79a261cd12b92879947bd340939a833a678632ce4f5c4a6feab4477e9c21cd43faac3b90b68b77dd0536c4149736 languageName: node linkType: hard @@ -10917,15 +9671,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e - languageName: node - linkType: hard - "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -10949,34 +9694,6 @@ __metadata: languageName: node linkType: hard -"toidentifier@npm:1.0.1": - version: 1.0.1 - resolution: "toidentifier@npm:1.0.1" - checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 - languageName: node - linkType: hard - -"tough-cookie@npm:^4.1.2": - version: 4.1.4 - resolution: "tough-cookie@npm:4.1.4" - dependencies: - psl: ^1.1.33 - punycode: ^2.1.1 - universalify: ^0.2.0 - url-parse: ^1.5.3 - checksum: 5815059f014c31179a303c673f753f7899a6fce94ac93712c88ea5f3c26e0c042b5f0c7a599a00f8e0feeca4615dba75c3dffc54f3c1a489978aa8205e09307c - languageName: node - linkType: hard - -"tr46@npm:^3.0.0": - version: 3.0.0 - resolution: "tr46@npm:3.0.0" - dependencies: - punycode: ^2.1.1 - checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270 - languageName: node - linkType: hard - "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -11063,13 +9780,6 @@ __metadata: languageName: node linkType: hard -"tty-browserify@npm:^0.0.1": - version: 0.0.1 - resolution: "tty-browserify@npm:0.0.1" - checksum: 93b745d43fa5a7d2b948fa23be8d313576d1d884b48acd957c07710bac1c0d8ac34c0556ad4c57c73d36e11741763ef66b3fb4fb97b06b7e4d525315a3cd45f5 - languageName: node - linkType: hard - "tty-table@npm:^4.1.5": version: 4.2.3 resolution: "tty-table@npm:4.2.3" @@ -11167,15 +9877,6 @@ __metadata: languageName: node linkType: hard -"type-check@npm:~0.3.2": - version: 0.3.2 - resolution: "type-check@npm:0.3.2" - dependencies: - prelude-ls: ~1.1.2 - checksum: dd3b1495642731bc0e1fc40abe5e977e0263005551ac83342ecb6f4f89551d106b368ec32ad3fb2da19b3bd7b2d1f64330da2ea9176d8ddbfe389fb286eb5124 - languageName: node - linkType: hard - "type-detect@npm:4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" @@ -11183,6 +9884,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 3b32f873cd02bc7001b00a61502b7ddc4b49278aabe68d652f732e1b5d768c072de0bc734b427abf59d0520a5f19a2e07309ab921ef02018fa1cb4af155cdb37 + languageName: node + linkType: hard + "type-fest@npm:^0.13.1": version: 0.13.1 resolution: "type-fest@npm:0.13.1" @@ -11218,16 +9926,6 @@ __metadata: languageName: node linkType: hard -"type-is@npm:~1.6.18": - version: 1.6.18 - resolution: "type-is@npm:1.6.18" - dependencies: - media-typer: 0.3.0 - mime-types: ~2.1.24 - checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 - languageName: node - linkType: hard - "typed-array-buffer@npm:^1.0.2": version: 1.0.2 resolution: "typed-array-buffer@npm:1.0.2" @@ -11376,10 +10074,10 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^0.7.30": - version: 0.7.35 - resolution: "ua-parser-js@npm:0.7.35" - checksum: 0a332e8d72d277e62f29ecb3a33843b274de93eb9378350b746ea0f89ef05ee09c94f2c1fdab8001373ad5e95a48beb0a94f39dc1670c908db9fc9b8f0876204 +"ufo@npm:^1.5.4": + version: 1.5.4 + resolution: "ufo@npm:1.5.4" + checksum: f244703b7d4f9f0df4f9af23921241ab73410b591f4e5b39c23e3147f3159b139a4b1fb5903189c306129f7a16b55995dac0008e0fbae88a37c3e58cbc34d833 languageName: node linkType: hard @@ -11430,20 +10128,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.2.0": - version: 0.2.0 - resolution: "universalify@npm:0.2.0" - checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 - languageName: node - linkType: hard - -"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": - version: 1.0.0 - resolution: "unpipe@npm:1.0.0" - checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 - languageName: node - linkType: hard - "update-browserslist-db@npm:^1.0.10": version: 1.0.10 resolution: "update-browserslist-db@npm:1.0.10" @@ -11481,26 +10165,6 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.5.3": - version: 1.5.10 - resolution: "url-parse@npm:1.5.10" - dependencies: - querystringify: ^2.1.1 - requires-port: ^1.0.0 - checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf - languageName: node - linkType: hard - -"url@npm:^0.11.0": - version: 0.11.1 - resolution: "url@npm:0.11.1" - dependencies: - punycode: ^1.4.1 - qs: ^6.11.0 - checksum: a7de4b37bbcbe60ef199acda4ce437ef843c0ef3a4b34ec3e3d97e0446a5f50dc7bfeafbe33ad118cf4e5aa04805e1328f0d0126e254f2b77bb8498fa395c596 - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -11508,26 +10172,6 @@ __metadata: languageName: node linkType: hard -"util@npm:^0.12.0, util@npm:^0.12.1": - version: 0.12.5 - resolution: "util@npm:0.12.5" - dependencies: - inherits: ^2.0.3 - is-arguments: ^1.0.4 - is-generator-function: ^1.0.7 - is-typed-array: ^1.1.3 - which-typed-array: ^1.1.2 - checksum: 705e51f0de5b446f4edec10739752ac25856541e0254ea1e7e45e5b9f9b0cb105bc4bd415736a6210edc68245a7f903bf085ffb08dd7deb8a0e847f60538a38a - languageName: node - linkType: hard - -"utils-merge@npm:1.0.1": - version: 1.0.1 - resolution: "utils-merge@npm:1.0.1" - checksum: c81095493225ecfc28add49c106ca4f09cdf56bc66731aa8dabc2edbbccb1e1bfe2de6a115e5c6a380d3ea166d1636410b62ef216bb07b3feb1cfde1d95d5080 - languageName: node - linkType: hard - "uuid@npm:^9.0.1": version: 9.0.1 resolution: "uuid@npm:9.0.1" @@ -11565,24 +10209,119 @@ __metadata: languageName: node linkType: hard -"vary@npm:^1": - version: 1.1.2 - resolution: "vary@npm:1.1.2" - checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b +"vite-node@npm:0.34.6": + version: 0.34.6 + resolution: "vite-node@npm:0.34.6" + dependencies: + cac: ^6.7.14 + debug: ^4.3.4 + mlly: ^1.4.0 + pathe: ^1.1.1 + picocolors: ^1.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0-0 + bin: + vite-node: vite-node.mjs + checksum: 46eba82bf8b69c7dfeed901502533b172cc6303212f0f49f82c2f64758fa4b60acd1b1e37cb96aff944e36b510b0d1beedb50d9cb25ef39e0159b2b9d1136b1f languageName: node linkType: hard -"vm-browserify@npm:^1.1.2": - version: 1.1.2 - resolution: "vm-browserify@npm:1.1.2" - checksum: 10a1c50aab54ff8b4c9042c15fc64aefccce8d2fb90c0640403242db0ee7fb269f9b102bdb69cfb435d7ef3180d61fd4fb004a043a12709abaf9056cfd7e039d +"vite@npm:4.5.5": + version: 4.5.5 + resolution: "vite@npm:4.5.5" + dependencies: + esbuild: ^0.18.10 + fsevents: ~2.3.2 + postcss: ^8.4.27 + rollup: ^3.27.1 + peerDependencies: + "@types/node": ">= 14" + less: "*" + lightningcss: ^1.21.0 + sass: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 300c5f39c83b22413dfdc84f72e9ba979bf4004e4d939409eea1470b116626294495b09e2bd73fae387a254b79988c8d54ceb281f9515120a0eda179c33b216e languageName: node linkType: hard -"void-elements@npm:^2.0.0": - version: 2.0.1 - resolution: "void-elements@npm:2.0.1" - checksum: 700c07ba9cfa2dff88bb23974b3173118f9ad8107143db9e5d753552be15cf93380954d4e7f7d7bc80e7306c35c3a7fb83ab0ce4d4dcc18abf90ca8b31452126 +"vitest@npm:0.34.6": + version: 0.34.6 + resolution: "vitest@npm:0.34.6" + dependencies: + "@types/chai": ^4.3.5 + "@types/chai-subset": ^1.3.3 + "@types/node": "*" + "@vitest/expect": 0.34.6 + "@vitest/runner": 0.34.6 + "@vitest/snapshot": 0.34.6 + "@vitest/spy": 0.34.6 + "@vitest/utils": 0.34.6 + acorn: ^8.9.0 + acorn-walk: ^8.2.0 + cac: ^6.7.14 + chai: ^4.3.10 + debug: ^4.3.4 + local-pkg: ^0.4.3 + magic-string: ^0.30.1 + pathe: ^1.1.1 + picocolors: ^1.0.0 + std-env: ^3.3.3 + strip-literal: ^1.0.1 + tinybench: ^2.5.0 + tinypool: ^0.7.0 + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 + vite-node: 0.34.6 + why-is-node-running: ^2.2.2 + peerDependencies: + "@edge-runtime/vm": "*" + "@vitest/browser": "*" + "@vitest/ui": "*" + happy-dom: "*" + jsdom: "*" + playwright: "*" + safaridriver: "*" + webdriverio: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + bin: + vitest: vitest.mjs + checksum: 45f5c1987fa8c76dbaf5db379bbdb4f6e3713c484e850149af38247b627e70016c1863286fd7fcfab08a1d98430f66ba1f45af6f14f5c467ded4b1ea6f26afa3 languageName: node linkType: hard @@ -11600,15 +10339,6 @@ __metadata: languageName: node linkType: hard -"w3c-xmlserializer@npm:^4.0.0": - version: 4.0.0 - resolution: "w3c-xmlserializer@npm:4.0.0" - dependencies: - xml-name-validator: ^4.0.0 - checksum: eba070e78deb408ae8defa4d36b429f084b2b47a4741c4a9be3f27a0a3d1845e277e3072b04391a138f7e43776842627d1334e448ff13ff90ad9fb1214ee7091 - languageName: node - linkType: hard - "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -11658,15 +10388,6 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:^4.1.5": - version: 4.2.2 - resolution: "webpack-merge@npm:4.2.2" - dependencies: - lodash: ^4.17.15 - checksum: ce58bc8ab53a3dd5d9a0df65684571349eef53372bf8f224521072110485391335b26ab097c5f07829b88d0c146056944149566e5a953f05997b0fe2cbaf8dd6 - languageName: node - linkType: hard - "webpack-sources@npm:^3.2.3": version: 3.2.3 resolution: "webpack-sources@npm:3.2.3" @@ -11711,15 +10432,6 @@ __metadata: languageName: node linkType: hard -"whatwg-encoding@npm:^2.0.0": - version: 2.0.0 - resolution: "whatwg-encoding@npm:2.0.0" - dependencies: - iconv-lite: 0.6.3 - checksum: 7087810c410aa9b689cbd6af8773341a53cdc1f3aae2a882c163bd5522ec8ca4cdfc269aef417a5792f411807d5d77d50df4c24e3abb00bb60192858a40cc675 - languageName: node - linkType: hard - "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0" @@ -11727,16 +10439,6 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^11.0.0": - version: 11.0.0 - resolution: "whatwg-url@npm:11.0.0" - dependencies: - tr46: ^3.0.0 - webidl-conversions: ^7.0.0 - checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af - languageName: node - linkType: hard - "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -11797,21 +10499,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.2": - version: 1.1.9 - resolution: "which-typed-array@npm:1.1.9" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - is-typed-array: ^1.1.10 - checksum: fe0178ca44c57699ca2c0e657b64eaa8d2db2372a4e2851184f568f98c478ae3dc3fdb5f7e46c384487046b0cf9e23241423242b277e03e8ba3dabc7c84c98ef - languageName: node - linkType: hard - -"which@npm:^1.2.1, which@npm:^1.2.9": +"which@npm:^1.2.9": version: 1.3.1 resolution: "which@npm:1.3.1" dependencies: @@ -11833,14 +10521,15 @@ __metadata: languageName: node linkType: hard -"which@npm:^3.0.0": - version: 3.0.1 - resolution: "which@npm:3.0.1" +"why-is-node-running@npm:^2.2.2": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" dependencies: - isexe: ^2.0.0 + siginfo: ^2.0.0 + stackback: 0.0.2 bin: - node-which: bin/which.js - checksum: adf720fe9d84be2d9190458194f814b5e9015ae4b88711b150f30d0f4d0b646544794b86f02c7ebeec1db2029bc3e83a7ff156f542d7521447e5496543e26890 + why-is-node-running: cli.js + checksum: 58ebbf406e243ace97083027f0df7ff4c2108baf2595bb29317718ef207cc7a8104e41b711ff65d6fa354f25daa8756b67f2f04931a4fd6ba9d13ae8197496fb languageName: node linkType: hard @@ -11860,13 +10549,6 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:~1.2.3": - version: 1.2.4 - resolution: "word-wrap@npm:1.2.4" - checksum: 8f1f2e0a397c0e074ca225ba9f67baa23f99293bc064e31355d426ae91b8b3f6b5f6c1fc9ae5e9141178bb362d563f55e62fd8d5c31f2a77e3ade56cb3e35bd1 - languageName: node - linkType: hard - "wrap-ansi@npm:^6.2.0": version: 6.2.0 resolution: "wrap-ansi@npm:6.2.0" @@ -11921,57 +10603,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0": - version: 8.17.0 - resolution: "ws@npm:8.17.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 147ef9eab0251364e1d2c55338ad0efb15e6913923ccbfdf20f7a8a6cb8f88432bcd7f4d8f66977135bfad35575644f9983201c1a361019594a4e53977bf6d4e - languageName: node - linkType: hard - -"ws@npm:~8.11.0": - version: 8.11.0 - resolution: "ws@npm:8.11.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 316b33aba32f317cd217df66dbfc5b281a2f09ff36815de222bc859e3424d83766d9eb2bd4d667de658b6ab7be151f258318fb1da812416b30be13103e5b5c67 - languageName: node - linkType: hard - -"xml-name-validator@npm:^4.0.0": - version: 4.0.0 - resolution: "xml-name-validator@npm:4.0.0" - checksum: af100b79c29804f05fa35aa3683e29a321db9b9685d5e5febda3fa1e40f13f85abc40f45a6b2bf7bee33f68a1dc5e8eaef4cec100a304a9db565e6061d4cb5ad - languageName: node - linkType: hard - -"xmlchars@npm:^2.2.0": - version: 2.2.0 - resolution: "xmlchars@npm:2.2.0" - checksum: 8c70ac94070ccca03f47a81fcce3b271bd1f37a591bf5424e787ae313fcb9c212f5f6786e1fa82076a2c632c0141552babcd85698c437506dfa6ae2d58723062 - languageName: node - linkType: hard - -"xtend@npm:^4.0.2": - version: 4.0.2 - resolution: "xtend@npm:4.0.2" - checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a - languageName: node - linkType: hard - "y18n@npm:^4.0.0": version: 4.0.3 resolution: "y18n@npm:4.0.3" @@ -12072,7 +10703,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^16.1.1, yargs@npm:^16.2.0": +"yargs@npm:^16.2.0": version: 16.2.0 resolution: "yargs@npm:16.2.0" dependencies: @@ -12129,6 +10760,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c + languageName: node + linkType: hard + "z-schema@npm:~5.0.2": version: 5.0.5 resolution: "z-schema@npm:5.0.5"