From 861535c4d83bf43f252463aa30ddd37b608169aa Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 24 Oct 2024 15:28:14 +0000 Subject: [PATCH 1/2] test(packages): convert to vitest --- lib/lib-storage/karma.conf.js | 30 --- package.json | 2 +- .../middleware-eventstream/jest.config.js | 5 - packages/middleware-sdk-sts/jest.config.js | 5 - .../polly-request-presigner/jest.config.js | 5 - packages/polly-request-presigner/package.json | 3 +- .../src/getSignedUrls.spec.ts | 44 ++--- .../polly-request-presigner/vitest.config.ts | 9 + packages/rds-signer/jest.config.js | 5 - packages/rds-signer/package.json | 3 +- packages/rds-signer/src/Signer.spec.ts | 23 +-- packages/rds-signer/src/index.spec.ts | 2 + packages/rds-signer/src/runtimeConfig.spec.ts | 2 + packages/rds-signer/vitest.config.ts | 9 + .../region-config-resolver/jest.config.js | 5 - packages/region-config-resolver/package.json | 3 +- .../src/regionConfig/config.spec.ts | 2 + .../src/regionConfig/getRealRegion.spec.ts | 10 +- .../src/regionConfig/isFipsRegion.spec.ts | 2 + .../regionConfig/resolveRegionConfig.spec.ts | 17 +- .../region-config-resolver/vitest.config.ts | 9 + .../src/createPresignedPost.e2e.spec.ts | 1 + packages/s3-request-presigner/jest.config.js | 5 - packages/s3-request-presigner/package.json | 3 +- .../src/getSignedUrl.spec.ts | 102 +++++----- .../src/presigner.spec.ts | 1 + .../s3-request-presigner/vitest.config.ts | 9 + packages/sha256-tree-hash/jest.config.js | 5 - packages/sha256-tree-hash/package.json | 3 +- packages/sha256-tree-hash/src/index.spec.ts | 1 + packages/sha256-tree-hash/vitest.config.ts | 9 + packages/signature-v4-crt/jest.config.js | 3 +- packages/signature-v4-crt/package.json | 2 +- .../signature-v4-multi-region/jest.config.js | 5 - .../signature-v4-multi-region/package.json | 3 +- .../src/SignatureV4MultiRegion.spec.ts | 33 +++- .../vitest.config.ts | 9 + packages/token-providers/jest.config.js | 5 - packages/token-providers/package.json | 3 +- packages/token-providers/src/fromSso.spec.ts | 186 +++++++++--------- .../token-providers/src/fromStatic.spec.ts | 3 +- .../src/getNewSsoOidcToken.spec.ts | 19 +- .../src/getSsoOidcClient.spec.ts | 56 +++--- .../token-providers/src/nodeProvider.spec.ts | 35 ++-- .../src/validateTokenExpiry.spec.ts | 1 + .../src/validateTokenKey.spec.ts | 1 + .../src/writeSSOTokenToFile.spec.ts | 13 +- packages/token-providers/vitest.config.ts | 9 + packages/types/src/abort.spec.ts | 2 + packages/util-arn-parser/jest.config.js | 5 - packages/util-arn-parser/package.json | 3 +- packages/util-arn-parser/src/index.spec.ts | 2 + packages/util-arn-parser/vitest.config.ts | 9 + packages/util-create-request/jest.config.js | 5 - packages/util-create-request/package.json | 3 +- .../util-create-request/src/index.spec.ts | 1 + packages/util-create-request/vitest.config.ts | 9 + packages/util-dns/jest.config.js | 6 - packages/util-dns/package.json | 3 +- .../util-dns/src/HostResolver.browser.spec.ts | 1 + packages/util-dns/src/HostResolver.spec.ts | 2 + .../src/NodeDnsLookupHostResolver.spec.ts | 9 +- .../NodeDnsResolveHostResolver.spec.ts | 1 + .../util/HostAddressEntryCollection.spec.ts | 1 + packages/util-dns/src/util/HostEntry.spec.ts | 9 +- .../util-dns/src/util/HostEntryTable.spec.ts | 1 + packages/util-dns/vitest.config.ts | 9 + packages/util-dynamodb/jest.config.js | 5 - packages/util-dynamodb/package.json | 3 +- .../util-dynamodb/src/NumberValue.spec.ts | 2 + .../util-dynamodb/src/convertToAttr.spec.ts | 1 + .../src/convertToAttrToNative.spec.ts | 2 + .../util-dynamodb/src/convertToNative.spec.ts | 1 + packages/util-dynamodb/src/marshall.spec.ts | 1 + .../util-dynamodb/src/marshallTypes.spec.ts | 2 + packages/util-dynamodb/src/unmarshall.spec.ts | 8 +- packages/util-dynamodb/vitest.config.ts | 9 + packages/util-endpoints/jest.config.integ.js | 4 - packages/util-endpoints/jest.config.js | 5 - packages/util-endpoints/package.json | 6 +- .../lib/aws/isVirtualHostableS3Bucket.spec.ts | 25 ++- .../src/lib/aws/parseArn.spec.ts | 1 + .../src/lib/aws/partition.spec.ts | 2 + .../src/resolveEndpoint.integ.spec.ts | 3 +- .../util-endpoints/vitest.config.integ.ts | 8 + packages/util-endpoints/vitest.config.ts | 9 + packages/util-format-url/jest.config.js | 5 - packages/util-format-url/package.json | 3 +- packages/util-format-url/src/index.spec.ts | 1 + packages/util-format-url/vitest.config.ts | 9 + packages/util-locate-window/jest.config.js | 5 - packages/util-locate-window/package.json | 3 +- packages/util-locate-window/src/index.spec.ts | 3 +- packages/util-locate-window/vitest.config.ts | 9 + .../util-user-agent-browser/jest.config.js | 6 - packages/util-user-agent-browser/package.json | 3 +- .../src/index.native.spec.ts | 6 +- .../util-user-agent-browser/src/index.spec.ts | 10 +- .../util-user-agent-browser/vitest.config.ts | 9 + packages/util-user-agent-node/jest.config.js | 5 - packages/util-user-agent-node/package.json | 3 +- .../src/defaultUserAgent.spec.ts | 65 +++--- .../util-user-agent-node/vitest.config.ts | 9 + packages/xhr-http-handler/jest.config.js | 7 - packages/xhr-http-handler/package.json | 3 +- packages/xhr-http-handler/src/index.spec.ts | 2 + .../src/xhr-http-handler.spec.ts | 3 +- packages/xhr-http-handler/vitest.config.ts | 9 + packages/xml-builder/jest.config.js | 5 - packages/xml-builder/package.json | 3 +- packages/xml-builder/src/XmlNode.spec.ts | 4 +- packages/xml-builder/src/XmlText.spec.ts | 2 + .../xml-builder/src/escape-attribute.spec.ts | 2 + .../xml-builder/src/escape-element.spec.ts | 2 + packages/xml-builder/src/index.spec.ts | 2 + packages/xml-builder/vitest.config.ts | 9 + private/aws-restjson-server/package.json | 2 +- .../package.json | 2 +- scripts/generate-clients/copy-to-clients.js | 2 +- scripts/validation/vitest-validation.js | 61 ++++-- vitest.config.e2e.ts | 2 +- vitest.config.integ.ts | 2 +- vitest.config.ts | 1 + 123 files changed, 672 insertions(+), 505 deletions(-) delete mode 100644 lib/lib-storage/karma.conf.js delete mode 100644 packages/middleware-eventstream/jest.config.js delete mode 100644 packages/middleware-sdk-sts/jest.config.js delete mode 100644 packages/polly-request-presigner/jest.config.js create mode 100644 packages/polly-request-presigner/vitest.config.ts delete mode 100644 packages/rds-signer/jest.config.js create mode 100644 packages/rds-signer/vitest.config.ts delete mode 100644 packages/region-config-resolver/jest.config.js create mode 100644 packages/region-config-resolver/vitest.config.ts delete mode 100644 packages/s3-request-presigner/jest.config.js create mode 100644 packages/s3-request-presigner/vitest.config.ts delete mode 100644 packages/sha256-tree-hash/jest.config.js create mode 100644 packages/sha256-tree-hash/vitest.config.ts delete mode 100644 packages/signature-v4-multi-region/jest.config.js create mode 100644 packages/signature-v4-multi-region/vitest.config.ts delete mode 100644 packages/token-providers/jest.config.js create mode 100644 packages/token-providers/vitest.config.ts delete mode 100644 packages/util-arn-parser/jest.config.js create mode 100644 packages/util-arn-parser/vitest.config.ts delete mode 100644 packages/util-create-request/jest.config.js create mode 100644 packages/util-create-request/vitest.config.ts delete mode 100644 packages/util-dns/jest.config.js create mode 100644 packages/util-dns/vitest.config.ts delete mode 100644 packages/util-dynamodb/jest.config.js create mode 100644 packages/util-dynamodb/vitest.config.ts delete mode 100644 packages/util-endpoints/jest.config.integ.js delete mode 100644 packages/util-endpoints/jest.config.js create mode 100644 packages/util-endpoints/vitest.config.integ.ts create mode 100644 packages/util-endpoints/vitest.config.ts delete mode 100644 packages/util-format-url/jest.config.js create mode 100644 packages/util-format-url/vitest.config.ts delete mode 100644 packages/util-locate-window/jest.config.js create mode 100644 packages/util-locate-window/vitest.config.ts delete mode 100644 packages/util-user-agent-browser/jest.config.js create mode 100644 packages/util-user-agent-browser/vitest.config.ts delete mode 100644 packages/util-user-agent-node/jest.config.js create mode 100644 packages/util-user-agent-node/vitest.config.ts delete mode 100644 packages/xhr-http-handler/jest.config.js create mode 100644 packages/xhr-http-handler/vitest.config.ts delete mode 100644 packages/xml-builder/jest.config.js create mode 100644 packages/xml-builder/vitest.config.ts diff --git a/lib/lib-storage/karma.conf.js b/lib/lib-storage/karma.conf.js deleted file mode 100644 index 97f4a6436df2a..0000000000000 --- a/lib/lib-storage/karma.conf.js +++ /dev/null @@ -1,30 +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: [ - { pattern: "src/**/*.ts", include: "false" }, - { pattern: "test/browser/upload.browser-spec.ts", include: "false" }, - ], - exclude: ["**/*.d.ts"], - preprocessors: { - "**/*.ts": "karma-typescript", - }, - reporters: ["spec", "karma-typescript"], - browsers: ["ChromeHeadlessNoSandbox"], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: "ChromeHeadless", - flags: ["--no-sandbox"], - }, - }, - karmaTypescriptConfig: { - tsconfig: "./tsconfig.json", - bundlerOptions: { - addNodeGlobals: true, - }, - }, - singleRun: true, - }); -}; diff --git a/package.json b/package.json index e44073302bbbf..ae0ae9b5ae413 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "lint:versions": "node scripts/runtime-dependency-version-check/runtime-dep-version-check.js", "lint:dependencies": "node scripts/runtime-dependency-version-check/check-dependencies.js", "local-publish": "node ./scripts/verdaccio-publish/index.js", - "test:all": "yarn build:all && jest --coverage --passWithNoTests && lerna run test --scope '@aws-sdk/{fetch-http-handler,hash-blob-browser}' && yarn test:versions && yarn test:integration", + "test:all": "yarn build:all && jest --passWithNoTests && lerna run test --scope '@aws-sdk/{fetch-http-handler,hash-blob-browser}' && yarn test:versions && yarn test:integration", "test:ci": "lerna run test --since origin/main", "test:e2e": "node ./scripts/turbo test:e2e && node ./tests/canary/canary", "test:e2e:legacy": "cucumber-js --fail-fast", diff --git a/packages/middleware-eventstream/jest.config.js b/packages/middleware-eventstream/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/middleware-eventstream/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/middleware-sdk-sts/jest.config.js b/packages/middleware-sdk-sts/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/middleware-sdk-sts/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/polly-request-presigner/jest.config.js b/packages/polly-request-presigner/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/polly-request-presigner/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/polly-request-presigner/package.json b/packages/polly-request-presigner/package.json index bc5772d2bd025..049ebe3ce096d 100644 --- a/packages/polly-request-presigner/package.json +++ b/packages/polly-request-presigner/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/polly-request-presigner/src/getSignedUrls.spec.ts b/packages/polly-request-presigner/src/getSignedUrls.spec.ts index 5629d8480fd63..c4cab121f7828 100644 --- a/packages/polly-request-presigner/src/getSignedUrls.spec.ts +++ b/packages/polly-request-presigner/src/getSignedUrls.spec.ts @@ -1,16 +1,15 @@ -const mockV4Sign = jest.fn(); -const mockPresign = jest.fn(); -const mockV4 = jest.fn().mockReturnValue({ - presign: mockPresign, - sign: mockV4Sign, -}); -jest.mock("@smithy/signature-v4", () => ({ - SignatureV4: mockV4, -})); +import { beforeEach, describe, expect, test as it, vi } from "vitest"; +vi.mock("@smithy/signature-v4", () => ({ + SignatureV4: vi.fn().mockReturnValue({ + presign: vi.fn(), + sign: vi.fn(), + }), +})); import { PollyClient, SynthesizeSpeechCommand } from "@aws-sdk/client-polly"; +import { SignatureV4 } from "@smithy/signature-v4"; -jest.mock("@aws-sdk/util-format-url", () => ({ +vi.mock("@aws-sdk/util-format-url", () => ({ formatUrl: (url: any) => url, })); @@ -19,6 +18,7 @@ import { AwsCredentialIdentity, RequestPresigningArguments } from "@smithy/types import { getSignedUrl } from "./getSignedUrls"; describe("getSignedUrl", () => { + const mockInstance = new SignatureV4({} as any); const credentials: AwsCredentialIdentity = { secretAccessKey: "unit-test", accessKeyId: "unit-test", @@ -27,12 +27,12 @@ describe("getSignedUrl", () => { const clientParams = { region: "us-foo-1", credentials }; beforeEach(() => { - mockPresign.mockReset(); + vi.mocked(mockInstance).presign.mockReset(); }); it("should call SignatureV4.sign", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockInstance).presign.mockReturnValue(mockPresigned as any); const client = new PollyClient(clientParams); const command = new SynthesizeSpeechCommand({ Text: "hello world, this is alex", @@ -41,15 +41,15 @@ describe("getSignedUrl", () => { }); const signed = await getSignedUrl(client, command); expect(signed).toBe(mockPresigned); - expect(mockPresign).toBeCalled(); - expect(mockV4Sign).not.toBeCalled(); + expect(vi.mocked(mockInstance).presign).toBeCalled(); + expect(vi.mocked(mockInstance).sign).not.toBeCalled(); expect(client.middlewareStack.remove("presignInterceptMiddleware")).toBe(false); expect(command.middlewareStack.remove("presignInterceptMiddleware")).toBe(false); }); it("should presign with signing region and service in context if exists", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockInstance).presign.mockReturnValue(mockPresigned as any); const signingRegion = "aws-foo-1"; const signingService = "bar"; const client = new PollyClient(clientParams); @@ -70,8 +70,8 @@ describe("getSignedUrl", () => { VoiceId: "Kimberly", }); await getSignedUrl(client, command); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][1]).toMatchObject({ + expect(vi.mocked(mockInstance).presign).toBeCalled(); + expect(vi.mocked(mockInstance).presign.mock.calls[0][1]).toMatchObject({ signingRegion, signingService, }); @@ -79,7 +79,7 @@ describe("getSignedUrl", () => { it("should presign with parameters from presign options if set", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockInstance).presign.mockReturnValue(mockPresigned as any); const options: RequestPresigningArguments = { signingRegion: "aws-foo-1", signingService: "bar", @@ -95,12 +95,12 @@ describe("getSignedUrl", () => { VoiceId: "Kimberly", }); await getSignedUrl(client, command, options); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][1]).toMatchObject(options); + expect(vi.mocked(mockInstance).presign).toBeCalled(); + expect(vi.mocked(mockInstance).presign.mock.calls[0][1]).toMatchObject(options); }); it("should not throw if called concurrently", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockInstance).presign.mockReturnValue(mockPresigned as any); const client = new PollyClient(clientParams); const command = new SynthesizeSpeechCommand({ Text: "hello world, this is alex", @@ -110,6 +110,6 @@ describe("getSignedUrl", () => { const result = await Promise.all([getSignedUrl(client, command), getSignedUrl(client, command)]); expect(result).toBeInstanceOf(Array); expect(result).toHaveLength(2); - expect(mockPresign).toHaveBeenCalledTimes(2); + expect(vi.mocked(mockInstance).presign).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/polly-request-presigner/vitest.config.ts b/packages/polly-request-presigner/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/polly-request-presigner/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/rds-signer/jest.config.js b/packages/rds-signer/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/rds-signer/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/rds-signer/package.json b/packages/rds-signer/package.json index 421afdfafff5e..0ae0d7b7763d0 100644 --- a/packages/rds-signer/package.json +++ b/packages/rds-signer/package.json @@ -14,7 +14,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "engines": { "node": ">=16.0.0" diff --git a/packages/rds-signer/src/Signer.spec.ts b/packages/rds-signer/src/Signer.spec.ts index 9639094efc897..8b085b5d3f433 100644 --- a/packages/rds-signer/src/Signer.spec.ts +++ b/packages/rds-signer/src/Signer.spec.ts @@ -3,22 +3,23 @@ import { formatUrl } from "@aws-sdk/util-format-url"; import { loadConfig } from "@smithy/node-config-provider"; import { HttpRequest } from "@smithy/protocol-http"; import { SignatureV4 } from "@smithy/signature-v4"; +import { beforeAll, beforeEach, describe, expect, test as it, vi } from "vitest"; import { Signer, SignerConfig } from "./Signer"; -const mockPresign = jest.fn(); -jest.mock("@smithy/signature-v4", () => { +const mockPresign = vi.fn(); +vi.mock("@smithy/signature-v4", () => { return { - SignatureV4: jest.fn().mockImplementation(() => { + SignatureV4: vi.fn().mockImplementation(() => { return { presign: mockPresign }; }), }; }); -jest.mock("@smithy/node-config-provider"); -jest.mock("@smithy/config-resolver"); -jest.mock("@aws-sdk/credential-providers"); -jest.mock("@aws-sdk/util-format-url"); +vi.mock("@smithy/node-config-provider"); +vi.mock("@smithy/config-resolver"); +vi.mock("@aws-sdk/credential-providers"); +vi.mock("@aws-sdk/util-format-url"); describe("rds-signer", () => { const minimalParams: SignerConfig = { @@ -28,11 +29,11 @@ describe("rds-signer", () => { }; beforeAll(() => { - (formatUrl as jest.Mock).mockReturnValue("https://testhost:5432?other=url¶meters=here"); + vi.mocked(formatUrl).mockReturnValue("https://testhost:5432?other=url¶meters=here"); }); beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should provide correct parameters to the SigV4 signer", async () => { @@ -40,8 +41,8 @@ describe("rds-signer", () => { accessKeyId: "xyz", secretAccessKey: "123", }; - (loadConfig as jest.Mock).mockReturnValue(async () => "us-foo-1"); - (fromNodeProviderChain as jest.Mock).mockReturnValue(async () => credentials); + vi.mocked(loadConfig).mockReturnValue(async () => "us-foo-1"); + vi.mocked(fromNodeProviderChain).mockReturnValue(async () => credentials); const signer = new Signer(minimalParams); await signer.getAuthToken(); //@ts-ignore diff --git a/packages/rds-signer/src/index.spec.ts b/packages/rds-signer/src/index.spec.ts index 65d93db9813ce..14f4759c33df7 100644 --- a/packages/rds-signer/src/index.spec.ts +++ b/packages/rds-signer/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import * as rdsSigner from "./index"; describe("rds-signer", () => { diff --git a/packages/rds-signer/src/runtimeConfig.spec.ts b/packages/rds-signer/src/runtimeConfig.spec.ts index 9d1683925a2b3..5e8bbf47c8faa 100644 --- a/packages/rds-signer/src/runtimeConfig.spec.ts +++ b/packages/rds-signer/src/runtimeConfig.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { getRuntimeConfig as getBrowserRuntimeConfig } from "./runtimeConfig.browser"; import { getRuntimeConfig as getRnRuntimeConfig } from "./runtimeConfig.native"; import { SignerConfig } from "./Signer"; diff --git a/packages/rds-signer/vitest.config.ts b/packages/rds-signer/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/rds-signer/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/region-config-resolver/jest.config.js b/packages/region-config-resolver/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/region-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/region-config-resolver/package.json b/packages/region-config-resolver/package.json index bdd72f2c79bd8..1aa519eb2364d 100644 --- a/packages/region-config-resolver/package.json +++ b/packages/region-config-resolver/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/region-config-resolver/src/regionConfig/config.spec.ts b/packages/region-config-resolver/src/regionConfig/config.spec.ts index 580f3e85280d9..0d85d0eca8065 100644 --- a/packages/region-config-resolver/src/regionConfig/config.spec.ts +++ b/packages/region-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/region-config-resolver/src/regionConfig/getRealRegion.spec.ts b/packages/region-config-resolver/src/regionConfig/getRealRegion.spec.ts index 5a27f4aa8303b..c0eae0d04282a 100644 --- a/packages/region-config-resolver/src/regionConfig/getRealRegion.spec.ts +++ b/packages/region-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/region-config-resolver/src/regionConfig/isFipsRegion.spec.ts b/packages/region-config-resolver/src/regionConfig/isFipsRegion.spec.ts index 283e763ab171e..64617eb981af8 100644 --- a/packages/region-config-resolver/src/regionConfig/isFipsRegion.spec.ts +++ b/packages/region-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/region-config-resolver/src/regionConfig/resolveRegionConfig.spec.ts b/packages/region-config-resolver/src/regionConfig/resolveRegionConfig.spec.ts index f5d4bda69ff27..b3aef695b8ff8 100644 --- a/packages/region-config-resolver/src/regionConfig/resolveRegionConfig.spec.ts +++ b/packages/region-config-resolver/src/regionConfig/resolveRegionConfig.spec.ts @@ -1,11 +1,12 @@ import { Provider } from "@smithy/types"; +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"; @@ -13,12 +14,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", () => { @@ -51,8 +52,8 @@ describe("RegionConfig", () => { let mockUseFipsEndpoint: boolean | Provider; 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(() => { @@ -70,7 +71,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/region-config-resolver/vitest.config.ts b/packages/region-config-resolver/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/region-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/s3-presigned-post/src/createPresignedPost.e2e.spec.ts b/packages/s3-presigned-post/src/createPresignedPost.e2e.spec.ts index 49d719c6e3546..e94d25782069f 100644 --- a/packages/s3-presigned-post/src/createPresignedPost.e2e.spec.ts +++ b/packages/s3-presigned-post/src/createPresignedPost.e2e.spec.ts @@ -2,6 +2,7 @@ // These params are established in /tests/e2e. import { NoSuchKey, S3 } from "@aws-sdk/client-s3"; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test as it } from "vitest"; + const FormData = require("form-data"); import { createReadStream, existsSync, rmSync, writeFileSync } from "fs"; diff --git a/packages/s3-request-presigner/jest.config.js b/packages/s3-request-presigner/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/s3-request-presigner/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/s3-request-presigner/package.json b/packages/s3-request-presigner/package.json index 4b4c9cfaf7fb1..aa03c2b1c31d2 100644 --- a/packages/s3-request-presigner/package.json +++ b/packages/s3-request-presigner/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/s3-request-presigner/src/getSignedUrl.spec.ts b/packages/s3-request-presigner/src/getSignedUrl.spec.ts index d202c80498ea8..05c2cb082469f 100644 --- a/packages/s3-request-presigner/src/getSignedUrl.spec.ts +++ b/packages/s3-request-presigner/src/getSignedUrl.spec.ts @@ -1,25 +1,25 @@ -const mockV4Sign = jest.fn(); -const mockV4Presign = jest.fn(); -const mockV4 = jest.fn().mockReturnValue({ - presign: mockV4Presign, - sign: mockV4Sign, -}); -jest.mock("@aws-sdk/signature-v4-multi-region", () => ({ - //@ts-ignore - ...jest.requireActual("@aws-sdk/signature-v4-multi-region"), - SignatureV4MultiRegion: mockV4, +import { beforeEach, describe, expect, test as it, vi } from "vitest"; + +vi.mock("@aws-sdk/signature-v4-multi-region", async () => ({ + ...((await vi.importActual("@aws-sdk/signature-v4-multi-region")) as any), + SignatureV4MultiRegion: vi.fn().mockImplementation(() => ({ + presign: vi.fn(), + sign: vi.fn(), + })), })); import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; +import { SignatureV4MultiRegion } from "@aws-sdk/signature-v4-multi-region"; -const mockPresign = jest.fn(); -const mockPresigner = jest.fn().mockReturnValue({ - presign: mockPresign, -}); -jest.mock("./presigner", () => ({ - S3RequestPresigner: mockPresigner, +vi.mock("./presigner", () => ({ + S3RequestPresigner: vi.fn().mockReturnValue({ + presign: vi.fn(), + }), })); -jest.mock("@aws-sdk/util-format-url", () => ({ + +import { S3RequestPresigner } from "./presigner"; + +vi.mock("@aws-sdk/util-format-url", () => ({ formatUrl: (url: any) => url, })); @@ -28,11 +28,11 @@ import { RequestPresigningArguments } from "@smithy/types"; import { getSignedUrl } from "./getSignedUrl"; -jest.mock("@smithy/middleware-endpoint", () => { - const originalModule = jest.requireActual("@smithy/middleware-endpoint"); +vi.mock("@smithy/middleware-endpoint", async () => { + const originalModule: any = await vi.importActual("@smithy/middleware-endpoint"); return { ...originalModule, - getEndpointFromInstructions: jest.fn(() => + getEndpointFromInstructions: vi.fn(() => Promise.resolve({ properties: { authSchemes: [{ name: "sigv4a", signingRegionSet: ["*"] }], @@ -43,17 +43,20 @@ jest.mock("@smithy/middleware-endpoint", () => { }); describe("getSignedUrl", () => { + const mockS3RequestPresigner = new S3RequestPresigner({} as any); + const mockSignatureV4MultiRegion = new SignatureV4MultiRegion({} as any); const clientParams = { region: "us-foo-1", }; beforeEach(() => { - mockPresign.mockReset(); + vi.mocked(mockS3RequestPresigner.presign).mockReset(); + vi.clearAllMocks(); }); it("should call S3Presigner.sign", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const client = new S3Client(clientParams); const command = new GetObjectCommand({ Bucket: "Bucket", @@ -66,9 +69,9 @@ describe("getSignedUrl", () => { const signed = await presignPromise; expect(signed).toBe(mockPresigned); - expect(mockPresign).toBeCalled(); - expect(mockV4Presign).not.toBeCalled(); - expect(mockV4Sign).not.toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); + expect(vi.mocked(mockSignatureV4MultiRegion).presign).not.toBeCalled(); + expect(vi.mocked(mockSignatureV4MultiRegion).sign).not.toBeCalled(); // do not add extra middleware to the client or command expect(client.middlewareStack.remove("presignInterceptMiddleware")).toBe(false); expect(command.middlewareStack.remove("presignInterceptMiddleware")).toBe(false); @@ -76,7 +79,7 @@ describe("getSignedUrl", () => { it("should presign with signing region and service in context if exists", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const signingRegion = "aws-foo-1"; const signingService = "bar"; const client = new S3Client(clientParams); @@ -96,8 +99,8 @@ describe("getSignedUrl", () => { Key: "Key", }); await getSignedUrl(client, command); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][1]).toMatchObject({ + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign).mock.calls[0][1]).toMatchObject({ signingRegion, signingService, }); @@ -105,7 +108,7 @@ describe("getSignedUrl", () => { it("should presign with parameters from presign options if set", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const options: RequestPresigningArguments = { signingRegion: "aws-foo-1", signingService: "bar", @@ -120,13 +123,13 @@ describe("getSignedUrl", () => { Key: "Key", }); await getSignedUrl(client, command, options); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][1]).toMatchObject(options); + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign).mock.calls[0][1]).toMatchObject(options); }); it("should not throw if it's called concurrently", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const client = new S3Client(clientParams); const command = new GetObjectCommand({ Bucket: "Bucket", @@ -152,13 +155,13 @@ describe("getSignedUrl", () => { { step: "serialize", priority: "low" } ); await getSignedUrl(client, command); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][0].headers[header]).toBeUndefined(); + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign).mock.calls[0][0].headers[header]).toBeUndefined(); } ); it("should set region to * when sigv4a is the auth scheme", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const client = new S3Client(clientParams); const command = new GetObjectCommand({ @@ -167,33 +170,31 @@ describe("getSignedUrl", () => { }); await getSignedUrl(client, command); - const presignerArgs = mockPresigner.mock.calls[0][0]; + const presignerArgs = vi.mocked(S3RequestPresigner).mock.calls[0][0] as any; const region = await presignerArgs.region(); expect(region).toBe("*"); - expect(mockPresign).toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); }); - // TODO(endpointsv2) fix this test - it.skip("should presign request with MRAP ARN", async () => { + it("should presign request with MRAP ARN", async () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const client = new S3Client(clientParams); const command = new GetObjectCommand({ Bucket: "arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap", Key: "Key", }); await getSignedUrl(client, command); - expect(mockPresign).toBeCalled(); - expect(mockPresign.mock.calls[0][0]).toMatchObject({ + expect(vi.mocked(mockS3RequestPresigner.presign)).toBeCalled(); + expect(vi.mocked(mockS3RequestPresigner.presign).mock.calls[0][0]).toMatchObject({ hostname: "mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com", }); }); - // TODO(endpointsv2) fix this test - it.skip("should throw if presign request with MRAP ARN and disableMultiregionAccessPoints option", () => { + it("should throw if presign request with MRAP ARN and disableMultiregionAccessPoints option", () => { const mockPresigned = "a presigned url"; - mockPresign.mockReturnValue(mockPresigned); + vi.mocked(mockS3RequestPresigner.presign).mockReturnValue(mockPresigned as any); const client = new S3Client({ ...clientParams, disableMultiregionAccessPoints: true, @@ -202,8 +203,13 @@ describe("getSignedUrl", () => { Bucket: "arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap", Key: "Key", }); - return expect(getSignedUrl(client, command)).rejects.toMatchObject({ - message: "SDK is attempting to use a MRAP ARN. Please enable to feature.", - }); + return expect(getSignedUrl(client, command)).rejects.toEqual( + new (class EndpointError extends Error { + constructor(...args: any[]) { + super(...args); + this.name = "EndpointError"; + } + })("Invalid configuration: Multi-Region Access Point ARNs are disabled.") + ); }); }); diff --git a/packages/s3-request-presigner/src/presigner.spec.ts b/packages/s3-request-presigner/src/presigner.spec.ts index c53164c1c3577..b809390cd576d 100644 --- a/packages/s3-request-presigner/src/presigner.spec.ts +++ b/packages/s3-request-presigner/src/presigner.spec.ts @@ -1,5 +1,6 @@ import { Hash } from "@smithy/hash-node"; import { HttpRequest } from "@smithy/protocol-http"; +import { describe, expect, test as it } from "vitest"; import { ALGORITHM_IDENTIFIER, diff --git a/packages/s3-request-presigner/vitest.config.ts b/packages/s3-request-presigner/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/s3-request-presigner/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/sha256-tree-hash/jest.config.js b/packages/sha256-tree-hash/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/sha256-tree-hash/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/sha256-tree-hash/package.json b/packages/sha256-tree-hash/package.json index 8b1414c59cbbb..24e443a5709ab 100644 --- a/packages/sha256-tree-hash/package.json +++ b/packages/sha256-tree-hash/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/sha256-tree-hash/src/index.spec.ts b/packages/sha256-tree-hash/src/index.spec.ts index 8ba36075829be..e77b683c6fc6c 100644 --- a/packages/sha256-tree-hash/src/index.spec.ts +++ b/packages/sha256-tree-hash/src/index.spec.ts @@ -1,6 +1,7 @@ import { Sha256 } from "@aws-crypto/sha256-js"; import { toHex } from "@smithy/util-hex-encoding"; import { fromUtf8 } from "@smithy/util-utf8"; +import { describe, expect, test as it } from "vitest"; import { TreeHash } from "./index"; diff --git a/packages/sha256-tree-hash/vitest.config.ts b/packages/sha256-tree-hash/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/sha256-tree-hash/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-crt/jest.config.js b/packages/signature-v4-crt/jest.config.js index 64f3d932819c3..f2c48a84f355c 100644 --- a/packages/signature-v4-crt/jest.config.js +++ b/packages/signature-v4-crt/jest.config.js @@ -2,6 +2,5 @@ const base = require("../../jest.config.base.js"); module.exports = { ...base, - //only test cjs dist, avoid testing the package twice - testPathIgnorePatterns: ["/node_modules/", "/es/"], + testPathIgnorePatterns: ["/node_modules/"], }; diff --git a/packages/signature-v4-crt/package.json b/packages/signature-v4-crt/package.json index 4ce6013d9a947..5752c659f28b0 100644 --- a/packages/signature-v4-crt/package.json +++ b/packages/signature-v4-crt/package.json @@ -14,7 +14,7 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest --coverage" + "test": "jest" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/signature-v4-multi-region/jest.config.js b/packages/signature-v4-multi-region/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/signature-v4-multi-region/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/signature-v4-multi-region/package.json b/packages/signature-v4-multi-region/package.json index 64b503124200d..0812e2e53b7e4 100644 --- a/packages/signature-v4-multi-region/package.json +++ b/packages/signature-v4-multi-region/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/signature-v4-multi-region/src/SignatureV4MultiRegion.spec.ts b/packages/signature-v4-multi-region/src/SignatureV4MultiRegion.spec.ts index 32ca2575d1a1d..9beb819c24449 100644 --- a/packages/signature-v4-multi-region/src/SignatureV4MultiRegion.spec.ts +++ b/packages/signature-v4-multi-region/src/SignatureV4MultiRegion.spec.ts @@ -1,11 +1,13 @@ import { HttpRequest } from "@smithy/protocol-http"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; -jest.mock("@smithy/signature-v4"); - -jest.mock("@aws-sdk/signature-v4-crt"); +vi.mock("@smithy/signature-v4"); +vi.mock("@aws-sdk/middleware-sdk-s3"); +vi.mock("@aws-sdk/signature-v4-crt"); +import { SignatureV4S3Express } from "@aws-sdk/middleware-sdk-s3"; import { CrtSignerV4 } from "@aws-sdk/signature-v4-crt"; -import { SignatureV4 } from "@smithy/signature-v4"; +import { Checksum } from "@smithy/types"; import { signatureV4CrtContainer } from "./signature-v4-crt-container"; import { SignatureV4MultiRegion, SignatureV4MultiRegionInit } from "./SignatureV4MultiRegion"; @@ -18,7 +20,21 @@ describe("SignatureV4MultiRegion", () => { accessKeyId: "akid", secretAccessKey: "secret", }, - sha256: (() => {}) as any, + sha256: class implements Checksum { + public data = new Uint8Array(); + public async digest() { + return this.data; + } + public update(bytes: Uint8Array) { + const oldData = this.data; + this.data = new Uint8Array(this.data.byteLength + bytes.byteLength); + this.data.set(oldData); + this.data.set(bytes, oldData.byteLength); + } + public reset() { + this.data = new Uint8Array(); + } + }, runtime: "node", }; const minimalRequest = new HttpRequest({ @@ -28,21 +44,22 @@ describe("SignatureV4MultiRegion", () => { beforeEach(() => { signatureV4CrtContainer.CrtSignerV4 = CrtSignerV4 as any; - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should sign with SigV4 signer", async () => { const signer = new SignatureV4MultiRegion(params); await signer.sign(minimalRequest); + //@ts-ignore - expect(SignatureV4.mock.instances[0].sign).toBeCalledTimes(1); + expect(SignatureV4S3Express.mock.instances[0].sign).toBeCalledTimes(1); }); it("should presign with SigV4 signer", async () => { const signer = new SignatureV4MultiRegion(params); await signer.presign(minimalRequest); //@ts-ignore - expect(SignatureV4.mock.instances[0].presign).toBeCalledTimes(1); + expect(SignatureV4S3Express.mock.instances[0].presign).toBeCalledTimes(1); }); it("should sign with SigV4a signer if mult_region option is set", async () => { diff --git a/packages/signature-v4-multi-region/vitest.config.ts b/packages/signature-v4-multi-region/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/signature-v4-multi-region/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/token-providers/jest.config.js b/packages/token-providers/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/token-providers/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/token-providers/package.json b/packages/token-providers/package.json index c6c67fbeaaf08..e5cb7959ddf56 100644 --- a/packages/token-providers/package.json +++ b/packages/token-providers/package.json @@ -14,7 +14,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "keywords": [ "aws", diff --git a/packages/token-providers/src/fromSso.spec.ts b/packages/token-providers/src/fromSso.spec.ts index 590b573d02ad8..20c906ad2df11 100644 --- a/packages/token-providers/src/fromSso.spec.ts +++ b/packages/token-providers/src/fromSso.spec.ts @@ -5,6 +5,7 @@ import { loadSsoSessionData, parseKnownFiles, } from "@smithy/shared-ini-file-loader"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { EXPIRE_WINDOW_MS, REFRESH_MESSAGE } from "./constants"; import { fromSso } from "./fromSso"; @@ -13,11 +14,11 @@ import { validateTokenExpiry } from "./validateTokenExpiry"; import { validateTokenKey } from "./validateTokenKey"; import { writeSSOTokenToFile } from "./writeSSOTokenToFile"; -jest.mock("@smithy/shared-ini-file-loader"); -jest.mock("./getNewSsoOidcToken"); -jest.mock("./validateTokenExpiry"); -jest.mock("./validateTokenKey"); -jest.mock("./writeSSOTokenToFile"); +vi.mock("@smithy/shared-ini-file-loader"); +vi.mock("./getNewSsoOidcToken"); +vi.mock("./validateTokenExpiry"); +vi.mock("./validateTokenKey"); +vi.mock("./writeSSOTokenToFile"); describe(fromSso.name, () => { const mockDateNow = Date.now(); @@ -54,25 +55,26 @@ describe(fromSso.name, () => { }; beforeEach(() => { - (parseKnownFiles as jest.Mock).mockResolvedValue(mockProfiles); - (loadSsoSessionData as jest.Mock).mockResolvedValue({ [mockSsoSessionName]: mockSsoSession }); - (getProfileName as jest.Mock).mockReturnValue(mockProfileName); - (getSSOTokenFromFile as jest.Mock).mockResolvedValue(mockSsoToken); - (getNewSsoOidcToken as jest.Mock).mockResolvedValue(mockNewTokenFromService); - (validateTokenKey as jest.Mock).mockImplementation(() => {}); - (validateTokenExpiry as jest.Mock).mockImplementation(() => {}); - jest.spyOn(Date, "now").mockReturnValue(mockDateNow); + vi.resetModules(); + vi.mocked(parseKnownFiles).mockResolvedValue(mockProfiles); + vi.mocked(loadSsoSessionData).mockResolvedValue({ [mockSsoSessionName]: mockSsoSession }); + vi.mocked(getProfileName).mockReturnValue(mockProfileName); + vi.mocked(getSSOTokenFromFile).mockResolvedValue(mockSsoToken); + vi.mocked(getNewSsoOidcToken).mockResolvedValue(mockNewTokenFromService); + vi.mocked(validateTokenKey).mockImplementation(() => {}); + vi.mocked(validateTokenExpiry).mockImplementation(() => {}); + vi.spyOn(Date, "now").mockReturnValue(mockDateNow); }); afterEach(() => { expect(parseKnownFiles).toHaveBeenCalledWith(mockInit); expect(getProfileName).toHaveBeenCalledWith(mockInit); - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("throws validation error", () => { it("when profile is not found", async () => { - (parseKnownFiles as jest.Mock).mockReturnValue({}); + vi.mocked(parseKnownFiles).mockReturnValue({}); const expectedError = new TokenProviderError( `Profile '${mockProfileName}' could not be found in shared credentials file.`, false @@ -82,7 +84,7 @@ describe(fromSso.name, () => { it("when sso_session is not defined for profile", async () => { const { sso_session, ...mockSsoProfileWithoutSsoSession } = mockSsoProfile; - (parseKnownFiles as jest.Mock).mockReturnValue({ [mockProfileName]: mockSsoProfileWithoutSsoSession }); + vi.mocked(parseKnownFiles).mockReturnValue({ [mockProfileName]: mockSsoProfileWithoutSsoSession }); const expectedError = new TokenProviderError( `Profile '${mockProfileName}' is missing required property 'sso_session'.` ); @@ -90,7 +92,7 @@ describe(fromSso.name, () => { }); it("when sso_session is not defined in configuration file", async () => { - (loadSsoSessionData as jest.Mock).mockResolvedValue({}); + vi.mocked(loadSsoSessionData).mockResolvedValue({}); const expectedError = new TokenProviderError( `Sso session '${mockSsoSessionName}' could not be found in shared credentials file.`, false @@ -100,7 +102,7 @@ describe(fromSso.name, () => { it("when sso-session does not contain sso_start_url", async () => { const { sso_start_url, ...mockSsoSessionWithoutSsoStartUrl } = mockSsoSession; - (loadSsoSessionData as jest.Mock).mockResolvedValue({ [mockSsoSessionName]: mockSsoSessionWithoutSsoStartUrl }); + vi.mocked(loadSsoSessionData).mockResolvedValue({ [mockSsoSessionName]: mockSsoSessionWithoutSsoStartUrl }); const expectedError = new TokenProviderError( `Sso session '${mockSsoSessionName}' is missing required property 'sso_start_url'.`, false @@ -110,7 +112,7 @@ describe(fromSso.name, () => { it("when profile contains sso_start_url, but no sso_region", async () => { const { sso_region, ...mockSsoSessionWithoutSsoStartUrl } = mockSsoSession; - (loadSsoSessionData as jest.Mock).mockResolvedValue({ [mockSsoSessionName]: mockSsoSessionWithoutSsoStartUrl }); + vi.mocked(loadSsoSessionData).mockResolvedValue({ [mockSsoSessionName]: mockSsoSessionWithoutSsoStartUrl }); const expectedError = new TokenProviderError( `Sso session '${mockSsoSessionName}' is missing required property 'sso_region'.`, false @@ -121,7 +123,7 @@ describe(fromSso.name, () => { it("throws error if reading SSO Token from file fails", async () => { const mockError = new Error("mockError"); - (getSSOTokenFromFile as jest.Mock).mockRejectedValue(mockError); + vi.mocked(getSSOTokenFromFile).mockRejectedValue(mockError); const expectedError = new TokenProviderError( `The SSO session token associated with profile=mockProfileName was not found or is invalid. ` + `${REFRESH_MESSAGE}`, @@ -132,14 +134,14 @@ describe(fromSso.name, () => { it.each(["accessToken", "expiresAt"])("throws error if %s is missing in SSO Token from file", async (key) => { const mockError = new Error("mockError"); - (validateTokenKey as jest.Mock).mockImplementation((validationKey) => { + vi.mocked(validateTokenKey).mockImplementation((validationKey) => { if (validationKey === key) { throw mockError; } }); await expect(fromSso(mockInit)()).rejects.toStrictEqual(mockError); expect(validateTokenKey).toHaveBeenNthCalledWith( - (validateTokenKey as jest.Mock).mock.calls.length, + vi.mocked(validateTokenKey).mock.calls.length, key, // @ts-ignore Element implicitly has an 'any' type mockSsoToken[key] @@ -151,7 +153,7 @@ describe(fromSso.name, () => { ...mockSsoToken, expiresAt: new Date(mockDateNow + EXPIRE_WINDOW_MS + 1000).toISOString(), }; - (getSSOTokenFromFile as jest.Mock).mockResolvedValueOnce(mockValidSsoToken); + vi.mocked(getSSOTokenFromFile).mockResolvedValueOnce(mockValidSsoToken); await expect(fromSso(mockInit)()).resolves.toStrictEqual({ token: mockValidSsoToken.accessToken, @@ -160,46 +162,40 @@ describe(fromSso.name, () => { }); describe("skips refresh attempt if last refresh was done within 30 seconds", () => { - it("throw if existing token is expired", (done) => { - jest.isolateModules(async () => { - const { fromSso } = require("./fromSso"); - await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); - expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); - expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); - - // Simulate token expiration. - const ssoTokenExpiryError = new TokenProviderError(`SSO Token is expired. ${REFRESH_MESSAGE}`, false); - (validateTokenExpiry as jest.Mock).mockImplementation(() => { - throw ssoTokenExpiryError; - }); - await expect(fromSso(mockInit)()).rejects.toStrictEqual(ssoTokenExpiryError); - // Verify that getNewSsoOidcToken is not called again. - expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); - done(); + it("throw if existing token is expired", async () => { + const { fromSso } = await import("./fromSso"); + await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); + expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); + expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); + + // Simulate token expiration. + const ssoTokenExpiryError = new TokenProviderError(`SSO Token is expired. ${REFRESH_MESSAGE}`, false); + vi.mocked(validateTokenExpiry).mockImplementation(() => { + throw ssoTokenExpiryError; }); + await expect(fromSso(mockInit)()).rejects.toStrictEqual(ssoTokenExpiryError); + // Verify that getNewSsoOidcToken is not called again. + expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); }); - it("returns existing token if it's not expired", (done) => { - jest.isolateModules(async () => { - const { fromSso } = require("./fromSso"); - await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); - expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); - expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); - - // Return a valid token for second call. - const mockValidSsoToken = { - ...mockSsoToken, - expiresAt: new Date(mockDateNow + EXPIRE_WINDOW_MS + 1000).toISOString(), - }; - (getSSOTokenFromFile as jest.Mock).mockResolvedValueOnce(mockValidSsoToken); - await expect(fromSso(mockInit)()).resolves.toStrictEqual({ - token: mockValidSsoToken.accessToken, - expiration: new Date(mockValidSsoToken.expiresAt), - }); - // Verify that getNewSsoOidcToken is not called again. - expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); - done(); + it("returns existing token if it's not expired", async () => { + const { fromSso } = await import("./fromSso"); + await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); + expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); + expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); + + // Return a valid token for second call. + const mockValidSsoToken = { + ...mockSsoToken, + expiresAt: new Date(mockDateNow + EXPIRE_WINDOW_MS + 1000).toISOString(), + }; + vi.mocked(getSSOTokenFromFile).mockResolvedValueOnce(mockValidSsoToken); + await expect(fromSso(mockInit)()).resolves.toStrictEqual({ + token: mockValidSsoToken.accessToken, + expiration: new Date(mockValidSsoToken.expiresAt), }); + // Verify that getNewSsoOidcToken is not called again. + expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); }); }); @@ -207,14 +203,14 @@ describe(fromSso.name, () => { "throws error if %s is missing in SSO Token from file", async (key) => { const mockError = new Error("mockError"); - (validateTokenKey as jest.Mock).mockImplementation((validationKey) => { + vi.mocked(validateTokenKey).mockImplementation((validationKey) => { if (validationKey === key) { throw mockError; } }); await expect(fromSso(mockInit)()).rejects.toStrictEqual(mockError); expect(validateTokenKey).toHaveBeenNthCalledWith( - (validateTokenKey as jest.Mock).mock.calls.length, + vi.mocked(validateTokenKey).mock.calls.length, key, // @ts-ignore Element implicitly has an 'any' type mockSsoToken[key], @@ -229,7 +225,7 @@ describe(fromSso.name, () => { ...mockSsoToken, expiresAt: new Date(mockDateNow + EXPIRE_WINDOW_MS - 1000).toISOString(), }; - (getSSOTokenFromFile as jest.Mock).mockResolvedValueOnce(mockValidSsoTokenInExpiryWindow); + vi.mocked(getSSOTokenFromFile).mockResolvedValueOnce(mockValidSsoTokenInExpiryWindow); await expect(fromSsoImpl(mockInit)()).resolves.toStrictEqual({ token: mockValidSsoTokenInExpiryWindow.accessToken, expiration: new Date(mockValidSsoTokenInExpiryWindow.expiresAt), @@ -239,7 +235,7 @@ describe(fromSso.name, () => { const throwErrorExpiredTokenTest = async (fromSsoImpl: typeof fromSso) => { const ssoTokenExpiryError = new TokenProviderError(`SSO Token is expired. ${REFRESH_MESSAGE}`, false); - (validateTokenExpiry as jest.Mock).mockImplementation(() => { + vi.mocked(validateTokenExpiry).mockImplementation(() => { throw ssoTokenExpiryError; }); await expect(fromSsoImpl(mockInit)()).rejects.toStrictEqual(ssoTokenExpiryError); @@ -251,25 +247,25 @@ describe(fromSso.name, () => { }); describe("when getNewSsoOidcToken throws error", () => { - it.each([returnExistingValidTokenInExpiryWindowTest, throwErrorExpiredTokenTest])("%p:", (testFn) => { - jest.isolateModules(async () => { - const { fromSso } = require("./fromSso"); + for (const testFn of [returnExistingValidTokenInExpiryWindowTest, throwErrorExpiredTokenTest]) { + it(testFn.name, async () => { + const { fromSso } = await import("./fromSso"); const mockError = new Error("mockError"); - (getNewSsoOidcToken as jest.Mock).mockImplementation(() => { + vi.mocked(getNewSsoOidcToken).mockImplementation(() => { throw mockError; }); testFn(fromSso); }); - }); + } }); describe.each(["accessToken", "expiresIn"])("when newSsoOidcToken does not contain key '%s'", (key) => { - it.each([returnExistingValidTokenInExpiryWindowTest, throwErrorExpiredTokenTest])("%p:", (testFn) => { - jest.isolateModules(async () => { + for (const testFn of [returnExistingValidTokenInExpiryWindowTest, throwErrorExpiredTokenTest]) { + it(testFn.name, async () => { let accessTokenFirstCallSuccess = false; - const { fromSso } = require("./fromSso"); + const { fromSso } = await import("./fromSso"); const mockError = new Error("mockError"); - (validateTokenKey as jest.Mock).mockImplementation((validationKey) => { + vi.mocked(validateTokenKey).mockImplementation((validationKey) => { if (validationKey === key) { // Skip first call of "accessToken" verification from ssoToken if (key === "accessToken" && !accessTokenFirstCallSuccess) { @@ -281,41 +277,37 @@ describe(fromSso.name, () => { }); testFn(fromSso); }); - }); + } }); }); it("returns valid access token from ssoOidc.createToken()", async () => { - jest.isolateModules(async () => { - const { fromSso } = require("./fromSso"); - await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); - expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); - expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); + const { fromSso } = await import("./fromSso"); + await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); + expect(getNewSsoOidcToken).toHaveBeenCalledTimes(1); + expect(getNewSsoOidcToken).toHaveBeenCalledWith(mockSsoToken, mockSsoSession.sso_region); - expect(writeSSOTokenToFile).toHaveBeenCalledWith(mockSsoSessionName, { - ...mockSsoToken, - accessToken: mockNewTokenFromService.accessToken, - expiresAt: mockNewToken.expiration.toISOString(), - refreshToken: mockNewTokenFromService.refreshToken, - }); + expect(writeSSOTokenToFile).toHaveBeenCalledWith(mockSsoSessionName, { + ...mockSsoToken, + accessToken: mockNewTokenFromService.accessToken, + expiresAt: mockNewToken.expiration.toISOString(), + refreshToken: mockNewTokenFromService.refreshToken, }); }); it("swallows error if writeSSOTokenToFile fails", async () => { - jest.isolateModules(async () => { - const mockError = new Error("mockError"); - (writeSSOTokenToFile as jest.Mock).mockImplementation(() => { - throw mockError; - }); - const { fromSso } = require("./fromSso"); - await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); + const mockError = new Error("mockError"); + vi.mocked(writeSSOTokenToFile).mockImplementation(() => { + throw mockError; + }); + const { fromSso } = await import("./fromSso"); + await expect(fromSso(mockInit)()).resolves.toStrictEqual(mockNewToken); - expect(writeSSOTokenToFile).toHaveBeenCalledWith(mockSsoSessionName, { - ...mockSsoToken, - accessToken: mockNewTokenFromService.accessToken, - expiresAt: mockNewToken.expiration.toISOString(), - refreshToken: mockNewTokenFromService.refreshToken, - }); + expect(writeSSOTokenToFile).toHaveBeenCalledWith(mockSsoSessionName, { + ...mockSsoToken, + accessToken: mockNewTokenFromService.accessToken, + expiresAt: mockNewToken.expiration.toISOString(), + refreshToken: mockNewTokenFromService.refreshToken, }); }); }); diff --git a/packages/token-providers/src/fromStatic.spec.ts b/packages/token-providers/src/fromStatic.spec.ts index eb91338a2794b..fdcffd7852740 100644 --- a/packages/token-providers/src/fromStatic.spec.ts +++ b/packages/token-providers/src/fromStatic.spec.ts @@ -1,4 +1,5 @@ import { TokenProviderError } from "@smithy/property-provider"; +import { afterEach, describe, expect, test as it, vi } from "vitest"; import { fromStatic } from "./fromStatic"; @@ -6,7 +7,7 @@ describe(fromStatic.name, () => { const errorMessage = "Please pass a valid token to fromStatic"; afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe("throws error", () => { diff --git a/packages/token-providers/src/getNewSsoOidcToken.spec.ts b/packages/token-providers/src/getNewSsoOidcToken.spec.ts index 7182ebb5903f7..ea7f87aef2da3 100644 --- a/packages/token-providers/src/getNewSsoOidcToken.spec.ts +++ b/packages/token-providers/src/getNewSsoOidcToken.spec.ts @@ -1,10 +1,11 @@ import { CreateTokenCommand } from "@aws-sdk/client-sso-oidc"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { getNewSsoOidcToken } from "./getNewSsoOidcToken"; import { getSsoOidcClient } from "./getSsoOidcClient"; -jest.mock("@aws-sdk/client-sso-oidc"); -jest.mock("./getSsoOidcClient"); +vi.mock("@aws-sdk/client-sso-oidc"); +vi.mock("./getSsoOidcClient"); describe(getNewSsoOidcToken.name, () => { let mockSend: any; @@ -30,16 +31,16 @@ describe(getNewSsoOidcToken.name, () => { }; beforeEach(() => { - mockSend = jest.fn().mockResolvedValueOnce(mockNewToken); - (getSsoOidcClient as jest.Mock).mockReturnValue({ send: mockSend }); - (CreateTokenCommand as unknown as jest.Mock).mockImplementation((args) => args); + mockSend = vi.fn().mockResolvedValueOnce(mockNewToken); + vi.mocked(getSsoOidcClient).mockReturnValue({ send: mockSend }); + (CreateTokenCommand as unknown as any).mockImplementation((args) => args); }); describe("re-throws", () => { const mockError = new Error("mockError"); it("if getSsoOidcClient throws", async () => { - (getSsoOidcClient as jest.Mock).mockImplementationOnce(() => { + vi.mocked(getSsoOidcClient).mockImplementationOnce(() => { throw mockError; }); try { @@ -54,8 +55,8 @@ describe(getNewSsoOidcToken.name, () => { }); it("if client.send() throws", async () => { - const mockSendWithError = jest.fn().mockRejectedValueOnce(mockError); - (getSsoOidcClient as jest.Mock).mockReturnValueOnce({ send: mockSendWithError }); + const mockSendWithError = vi.fn().mockRejectedValueOnce(mockError); + vi.mocked(getSsoOidcClient).mockReturnValueOnce({ send: mockSendWithError }); try { await getNewSsoOidcToken(mockSsoToken, mockSsoRegion); fail(`expected ${mockError}`); @@ -68,7 +69,7 @@ describe(getNewSsoOidcToken.name, () => { }); it("if CreateTokenCommand throws", async () => { - (CreateTokenCommand as unknown as jest.Mock).mockImplementation(() => { + (CreateTokenCommand as unknown as any).mockImplementation(() => { throw mockError; }); try { diff --git a/packages/token-providers/src/getSsoOidcClient.spec.ts b/packages/token-providers/src/getSsoOidcClient.spec.ts index 43935bffe104e..109f897aa09c4 100644 --- a/packages/token-providers/src/getSsoOidcClient.spec.ts +++ b/packages/token-providers/src/getSsoOidcClient.spec.ts @@ -1,49 +1,45 @@ import { SSOOIDCClient } from "@aws-sdk/client-sso-oidc"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; -jest.mock("@aws-sdk/client-sso-oidc"); +vi.mock("@aws-sdk/client-sso-oidc"); describe("getSsoOidcClient", () => { const mockSsoRegion = "mockSsoRegion"; const getMockClient = (region: string) => ({ region }); beforeEach(() => { - (SSOOIDCClient as jest.Mock).mockImplementation(({ region }) => getMockClient(region)); + vi.resetModules(); + vi.mocked(SSOOIDCClient).mockImplementation((({ region }) => getMockClient(region)) as any); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); - it("creates new SSOOIDC client", () => { - jest.isolateModules(async () => { - const { getSsoOidcClient } = require("./getSsoOidcClient"); - expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); - expect(SSOOIDCClient).toHaveBeenCalledTimes(1); - }); + it("creates new SSOOIDC client", async () => { + const { getSsoOidcClient } = await import("./getSsoOidcClient"); + expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); + expect(SSOOIDCClient).toHaveBeenCalledTimes(1); }); - it("returns SSOOIDC client from hash if already created", () => { - jest.isolateModules(async () => { - const { getSsoOidcClient } = require("./getSsoOidcClient"); - expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); - expect(SSOOIDCClient).toHaveBeenCalledTimes(1); - expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); - expect(SSOOIDCClient).toHaveBeenCalledTimes(1); - }); + it("returns SSOOIDC client from hash if already created", async () => { + const { getSsoOidcClient } = await import("./getSsoOidcClient"); + expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); + expect(SSOOIDCClient).toHaveBeenCalledTimes(1); + expect(await getSsoOidcClient(mockSsoRegion)).toEqual(getMockClient(mockSsoRegion) as any); + expect(SSOOIDCClient).toHaveBeenCalledTimes(1); }); - it("creates new SSOOIDC client per region", () => { - jest.isolateModules(async () => { - const { getSsoOidcClient } = require("./getSsoOidcClient"); - const mockSsoRegion1 = `${mockSsoRegion}1`; - expect(await getSsoOidcClient(mockSsoRegion1)).toEqual(getMockClient(mockSsoRegion1) as any); - expect(SSOOIDCClient).toHaveBeenCalledTimes(1); - expect(SSOOIDCClient).toHaveBeenCalledWith({ region: mockSsoRegion1 }); - - const mockSsoRegion2 = `${mockSsoRegion}2`; - expect(await getSsoOidcClient(mockSsoRegion2)).toEqual(getMockClient(mockSsoRegion2) as any); - expect(SSOOIDCClient).toHaveBeenCalledTimes(2); - expect(SSOOIDCClient).toHaveBeenNthCalledWith(2, { region: mockSsoRegion2 }); - }); + it("creates new SSOOIDC client per region", async () => { + const { getSsoOidcClient } = await import("./getSsoOidcClient"); + const mockSsoRegion1 = `${mockSsoRegion}1`; + expect(await getSsoOidcClient(mockSsoRegion1)).toEqual(getMockClient(mockSsoRegion1) as any); + expect(SSOOIDCClient).toHaveBeenCalledTimes(1); + expect(SSOOIDCClient).toHaveBeenCalledWith({ region: mockSsoRegion1 }); + + const mockSsoRegion2 = `${mockSsoRegion}2`; + expect(await getSsoOidcClient(mockSsoRegion2)).toEqual(getMockClient(mockSsoRegion2) as any); + expect(SSOOIDCClient).toHaveBeenCalledTimes(2); + expect(SSOOIDCClient).toHaveBeenNthCalledWith(2, { region: mockSsoRegion2 }); }); }); diff --git a/packages/token-providers/src/nodeProvider.spec.ts b/packages/token-providers/src/nodeProvider.spec.ts index df1ee5f112e6b..d993d197ffecd 100644 --- a/packages/token-providers/src/nodeProvider.spec.ts +++ b/packages/token-providers/src/nodeProvider.spec.ts @@ -1,12 +1,13 @@ import { chain, memoize, TokenProviderError } from "@smithy/property-provider"; import { loadSharedConfigFiles } from "@smithy/shared-ini-file-loader"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; import { fromSso } from "./fromSso"; import { nodeProvider } from "./nodeProvider"; -jest.mock("@smithy/property-provider"); -jest.mock("@smithy/shared-ini-file-loader"); -jest.mock("./fromSso"); +vi.mock("@smithy/property-provider"); +vi.mock("@smithy/shared-ini-file-loader"); +vi.mock("./fromSso"); describe(nodeProvider.name, () => { const mockToken = { @@ -18,9 +19,9 @@ describe(nodeProvider.name, () => { profile: "mockProfile", }; - const mockSsoFn = jest.fn(); - const mockChainFn = jest.fn(); - const mockMemoizeFn = jest.fn().mockResolvedValue(mockToken); + const mockSsoFn = vi.fn(); + const mockChainFn = vi.fn(); + const mockMemoizeFn = vi.fn().mockResolvedValue(mockToken); beforeEach(() => { [ @@ -28,15 +29,15 @@ describe(nodeProvider.name, () => { [chain, mockChainFn], [memoize, mockMemoizeFn], ].forEach(([fromFn, mockFn]) => { - (fromFn as jest.Mock).mockReturnValue(mockFn); + vi.mocked(fromFn).mockReturnValue(mockFn); }); }); afterEach(async () => { expect(chain).toHaveBeenCalledWith(mockSsoFn, expect.any(Function)); - const errorFnIndex = (chain as jest.Mock).mock.calls[0].length; - const errorFn = (chain as jest.Mock).mock.calls[0][errorFnIndex - 1]; + const errorFnIndex = vi.mocked(chain).mock.calls[0].length; + const errorFn = vi.mocked(chain).mock.calls[0][errorFnIndex - 1]; const expectedError = new TokenProviderError("Could not load token from any providers", false); try { await errorFn(); @@ -47,7 +48,7 @@ describe(nodeProvider.name, () => { expect(memoize).toHaveBeenCalledWith(mockChainFn, expect.any(Function), expect.any(Function)); - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("creates provider chain and memoizes it", async () => { @@ -64,30 +65,30 @@ describe(nodeProvider.name, () => { describe("memoize isExpired", () => { const mockDateNow = Date.now(); beforeEach(async () => { - jest.spyOn(Date, "now").mockReturnValueOnce(mockDateNow); + vi.spyOn(Date, "now").mockReturnValueOnce(mockDateNow); await nodeProvider(mockInit)(); }); it("returns true if expiration is defined, and token has expired", () => { - const memoizeExpiredFn = (memoize as jest.Mock).mock.calls[0][1]; + const memoizeExpiredFn = vi.mocked(memoize).mock.calls[0][1]; const expiration = new Date(mockDateNow - 24 * 60 * 60 * 1000); expect(memoizeExpiredFn({ expiration })).toEqual(true); }); it("returns true if expiration is defined, and token expires in <5 mins", () => { - const memoizeExpiredFn = (memoize as jest.Mock).mock.calls[0][1]; + const memoizeExpiredFn = vi.mocked(memoize).mock.calls[0][1]; const expiration = new Date(mockDateNow + 299 * 1000); expect(memoizeExpiredFn({ expiration })).toEqual(true); }); it("returns false if expiration is defined, but token expires in >5 mins", () => { - const memoizeExpiredFn = (memoize as jest.Mock).mock.calls[0][1]; + const memoizeExpiredFn = vi.mocked(memoize).mock.calls[0][1]; const expiration = new Date(mockDateNow + 301 * 1000); expect(memoizeExpiredFn({ expiration })).toEqual(false); }); it("returns false if expiration is not defined", () => { - const memoizeExpiredFn = (memoize as jest.Mock).mock.calls[0][1]; + const memoizeExpiredFn = vi.mocked(memoize).mock.calls[0][1]; expect(memoizeExpiredFn({})).toEqual(false); }); }); @@ -98,13 +99,13 @@ describe(nodeProvider.name, () => { }); it("returns true if expiration is not defined", () => { - const memoizeRefreshFn = (memoize as jest.Mock).mock.calls[0][2]; + const memoizeRefreshFn = vi.mocked(memoize).mock.calls[0][2]; const expiration = Date.now(); expect(memoizeRefreshFn({ expiration })).toEqual(true); }); it("returns false if expiration is not defined", () => { - const memoizeRefreshFn = (memoize as jest.Mock).mock.calls[0][2]; + const memoizeRefreshFn = vi.mocked(memoize).mock.calls[0][2]; expect(memoizeRefreshFn({})).toEqual(false); }); }); diff --git a/packages/token-providers/src/validateTokenExpiry.spec.ts b/packages/token-providers/src/validateTokenExpiry.spec.ts index 0a1a17ad26f80..09026a067ab9a 100644 --- a/packages/token-providers/src/validateTokenExpiry.spec.ts +++ b/packages/token-providers/src/validateTokenExpiry.spec.ts @@ -1,4 +1,5 @@ import { TokenProviderError } from "@smithy/property-provider"; +import { describe, expect, test as it } from "vitest"; import { REFRESH_MESSAGE } from "./constants"; import { validateTokenExpiry } from "./validateTokenExpiry"; diff --git a/packages/token-providers/src/validateTokenKey.spec.ts b/packages/token-providers/src/validateTokenKey.spec.ts index 354d3fdabae4c..86bd7325ea437 100644 --- a/packages/token-providers/src/validateTokenKey.spec.ts +++ b/packages/token-providers/src/validateTokenKey.spec.ts @@ -1,4 +1,5 @@ import { TokenProviderError } from "@smithy/property-provider"; +import { describe, expect, test as it } from "vitest"; import { REFRESH_MESSAGE } from "./constants"; import { validateTokenKey } from "./validateTokenKey"; diff --git a/packages/token-providers/src/writeSSOTokenToFile.spec.ts b/packages/token-providers/src/writeSSOTokenToFile.spec.ts index b35137f00de35..cd863d90294b4 100644 --- a/packages/token-providers/src/writeSSOTokenToFile.spec.ts +++ b/packages/token-providers/src/writeSSOTokenToFile.spec.ts @@ -1,11 +1,12 @@ import { getSSOTokenFilepath } from "@smithy/shared-ini-file-loader"; // 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 { writeSSOTokenToFile } from "./writeSSOTokenToFile"; -jest.mock("fs", () => ({ promises: { writeFile: jest.fn() } })); -jest.mock("@smithy/shared-ini-file-loader"); +vi.mock("fs", () => ({ promises: { writeFile: vi.fn() } })); +vi.mock("@smithy/shared-ini-file-loader"); describe(writeSSOTokenToFile.name, () => { const mockSsoStartUrl = "mock_sso_start_url"; @@ -17,17 +18,17 @@ describe(writeSSOTokenToFile.name, () => { }; beforeEach(() => { - (getSSOTokenFilepath as jest.Mock).mockReturnValue(mockSsoTokenFilepath); + vi.mocked(getSSOTokenFilepath).mockReturnValue(mockSsoTokenFilepath); }); afterEach(() => { expect(getSSOTokenFilepath).toHaveBeenCalledWith(mockSsoStartUrl); - 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(writeSSOTokenToFile.name, () => { it("re-throws if writeFile fails", async () => { const expectedError = new Error("error"); - (promises.writeFile as jest.Mock).mockRejectedValueOnce(expectedError); + (promises.writeFile as any).mockRejectedValueOnce(expectedError); try { await writeSSOTokenToFile(mockSsoStartUrl, mockSsoToken); diff --git a/packages/token-providers/vitest.config.ts b/packages/token-providers/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/token-providers/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/abort.spec.ts b/packages/types/src/abort.spec.ts index baf851ca492ac..bb3d917effb82 100644 --- a/packages/types/src/abort.spec.ts +++ b/packages/types/src/abort.spec.ts @@ -1,3 +1,5 @@ +import { test as it } from "vitest"; + import { AbortSignal } from "./abort"; // asserts that the global abortController signal is compatible with diff --git a/packages/util-arn-parser/jest.config.js b/packages/util-arn-parser/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-arn-parser/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-arn-parser/package.json b/packages/util-arn-parser/package.json index e28658165d878..2a61235ad2267 100644 --- a/packages/util-arn-parser/package.json +++ b/packages/util-arn-parser/package.json @@ -12,7 +12,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-arn-parser/src/index.spec.ts b/packages/util-arn-parser/src/index.spec.ts index bea4c14a18f10..21b5a60f02492 100644 --- a/packages/util-arn-parser/src/index.spec.ts +++ b/packages/util-arn-parser/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { build, parse, validate } from "./index"; describe("validate", () => { diff --git a/packages/util-arn-parser/vitest.config.ts b/packages/util-arn-parser/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-arn-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-create-request/jest.config.js b/packages/util-create-request/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-create-request/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-create-request/package.json b/packages/util-create-request/package.json index e0885294f0707..63c793628857a 100644 --- a/packages/util-create-request/package.json +++ b/packages/util-create-request/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-create-request/src/index.spec.ts b/packages/util-create-request/src/index.spec.ts index c14db15cd9e88..42037c50088b6 100644 --- a/packages/util-create-request/src/index.spec.ts +++ b/packages/util-create-request/src/index.spec.ts @@ -8,6 +8,7 @@ import { MiddlewareStack, SerializeHandlerArguments, } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { createRequest } from "./index"; diff --git a/packages/util-create-request/vitest.config.ts b/packages/util-create-request/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-create-request/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-dns/jest.config.js b/packages/util-dns/jest.config.js deleted file mode 100644 index 95d8863b22a18..0000000000000 --- a/packages/util-dns/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-dns/package.json b/packages/util-dns/package.json index 61bb79d92d16a..9a5511bcd3c0e 100644 --- a/packages/util-dns/package.json +++ b/packages/util-dns/package.json @@ -12,7 +12,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "keywords": [ "dns" diff --git a/packages/util-dns/src/HostResolver.browser.spec.ts b/packages/util-dns/src/HostResolver.browser.spec.ts index eda11823aab4a..842229c2c4773 100644 --- a/packages/util-dns/src/HostResolver.browser.spec.ts +++ b/packages/util-dns/src/HostResolver.browser.spec.ts @@ -2,6 +2,7 @@ * @jest-environment jsdom */ import { HostAddress, HostAddressType, HostResolverArguments } from "@aws-sdk/types"; +import { describe, expect, test as it } from "vitest"; import { HostResolver } from "./HostResolver.browser"; diff --git a/packages/util-dns/src/HostResolver.spec.ts b/packages/util-dns/src/HostResolver.spec.ts index 188be23a39533..f2ddb2fe9db23 100644 --- a/packages/util-dns/src/HostResolver.spec.ts +++ b/packages/util-dns/src/HostResolver.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { HostResolver } from "./HostResolver"; import { NodeDnsLookupHostResolver } from "./NodeDnsLookupHostResolver"; diff --git a/packages/util-dns/src/NodeDnsLookupHostResolver.spec.ts b/packages/util-dns/src/NodeDnsLookupHostResolver.spec.ts index 028e2585924a6..4ee08767a261a 100644 --- a/packages/util-dns/src/NodeDnsLookupHostResolver.spec.ts +++ b/packages/util-dns/src/NodeDnsLookupHostResolver.spec.ts @@ -1,5 +1,6 @@ import { HostAddress, HostAddressType, HostResolverArguments } from "@aws-sdk/types"; import { LookupAddress } from "dns"; +import { beforeEach, describe, expect, test, vi } from "vitest"; import { NodeDnsLookupHostResolver } from "./NodeDnsLookupHostResolver"; import { HostEntryTable } from "./util/HostEntryTable"; @@ -38,7 +39,7 @@ describe(NodeDnsLookupHostResolver.name, () => { let TEST_HOST_RESOLVER_TABLE: HostEntryTable; let TEST_HOST_RESOLVER: NodeDnsLookupHostResolver; beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); TEST_HOST_RESOLVER_TABLE = new HostEntryTable(); TEST_HOST_RESOLVER = new NodeDnsLookupHostResolver({ cache: TEST_HOST_RESOLVER_TABLE, @@ -406,7 +407,7 @@ describe(NodeDnsLookupHostResolver.name, () => { expectedIpV4Size: 1, expectedIpV6Size: 2, }); - jest.advanceTimersByTime(30_000); + vi.advanceTimersByTime(30_000); // Second resolveAddress() call which fails to update await TEST_HOST_RESOLVER.resolveAddress(TEST_HOST_RESOLVER_ARGUMENTS); await testResolveAddressOnce({ @@ -480,7 +481,7 @@ describe(NodeDnsLookupHostResolver.name, () => { expectedIpV4Size: 1, expectedIpV6Size: 1, }); - jest.advanceTimersByTime(30_000); + vi.advanceTimersByTime(30_000); // Second resolveAddress() call with an update await testResolveAddressOnce({ expectedIpV4Address: TEST_A_HOST_ADDRESS_0, @@ -591,7 +592,7 @@ describe(NodeDnsLookupHostResolver.name, () => { TEST_HOST_RESOLVER.reportFailureOnAddress(TEST_A_HOST_ADDRESS_0); TEST_HOST_RESOLVER.reportFailureOnAddress(TEST_AAAA_HOST_ADDRESS_0); TEST_HOST_RESOLVER.reportFailureOnAddress(TEST_AAAA_HOST_ADDRESS_1); - jest.advanceTimersByTime(30_000); + vi.advanceTimersByTime(30_000); // Second resolveAddress() call with no upgrades await expect(TEST_HOST_RESOLVER.resolveAddress(TEST_HOST_RESOLVER_ARGUMENTS)).rejects.toThrowError( 'Could not resolve addresses for "TEST_HOST_NAME"' diff --git a/packages/util-dns/src/archive/NodeDnsResolveHostResolver.spec.ts b/packages/util-dns/src/archive/NodeDnsResolveHostResolver.spec.ts index aab90fa5e293a..152f3c8d955a1 100644 --- a/packages/util-dns/src/archive/NodeDnsResolveHostResolver.spec.ts +++ b/packages/util-dns/src/archive/NodeDnsResolveHostResolver.spec.ts @@ -1,4 +1,5 @@ import { HostAddress, HostAddressType, HostResolverArguments } from "@aws-sdk/types"; +import { describe, expect, test } from "vitest"; import { NodeDnsResolveHostResolver } from "./NodeDnsResolveHostResolver"; diff --git a/packages/util-dns/src/util/HostAddressEntryCollection.spec.ts b/packages/util-dns/src/util/HostAddressEntryCollection.spec.ts index 42660a896844e..8f4a03c9880e4 100644 --- a/packages/util-dns/src/util/HostAddressEntryCollection.spec.ts +++ b/packages/util-dns/src/util/HostAddressEntryCollection.spec.ts @@ -1,4 +1,5 @@ import { HostAddressType } from "@aws-sdk/types"; +import { beforeEach, describe, expect, test as it } from "vitest"; import { HostAddressEntryCollection } from "./HostAddressEntryCollection"; import { HostAddressEntry } from "./HostEntry"; diff --git a/packages/util-dns/src/util/HostEntry.spec.ts b/packages/util-dns/src/util/HostEntry.spec.ts index 1d2d73ce5b38b..09baf333c84a7 100644 --- a/packages/util-dns/src/util/HostEntry.spec.ts +++ b/packages/util-dns/src/util/HostEntry.spec.ts @@ -1,4 +1,5 @@ import { HostAddress, HostAddressType } from "@aws-sdk/types"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { HostAddressEntry, HostEntry } from "./HostEntry"; @@ -34,7 +35,7 @@ describe(HostEntry.name, () => { let expirationTtlMs: number; beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); hostEntry = new HostEntry(Date.now()); expirationTtlMs = Date.now() + EXPIRATION_OFFSET_MS; addresses = [HOST_ADDRESS_A_0, HOST_ADDRESS_A_1, HOST_ADDRESS_AAAA_0, HOST_ADDRESS_AAAA_1]; @@ -88,7 +89,7 @@ describe(HostEntry.name, () => { describe("processRecords()", () => { it("removes expired records from good records except 1 good record", () => { hostEntry.updateRecords(addresses, expirationTtlMs); - jest.advanceTimersByTime(EXPIRATION_OFFSET_MS); + vi.advanceTimersByTime(EXPIRATION_OFFSET_MS); hostEntry.processRecords(); expect(hostEntry.aRecords.length).toEqual(1); expect(hostEntry.failedARecords.length).toEqual(0); @@ -102,7 +103,7 @@ describe(HostEntry.name, () => { hostEntry.failAddressInRecords(HOST_ADDRESS_A_1); hostEntry.failAddressInRecords(HOST_ADDRESS_AAAA_0); hostEntry.failAddressInRecords(HOST_ADDRESS_AAAA_1); - jest.advanceTimersByTime(EXPIRATION_OFFSET_MS); + vi.advanceTimersByTime(EXPIRATION_OFFSET_MS); hostEntry.processRecords(); expect(hostEntry.aRecords.length).toEqual(0); expect(hostEntry.failedARecords.length).toEqual(1); @@ -129,7 +130,7 @@ describe(HostEntry.name, () => { hostEntry.failAddressInRecords(HOST_ADDRESS_A_1); hostEntry.failAddressInRecords(HOST_ADDRESS_AAAA_0); hostEntry.failAddressInRecords(HOST_ADDRESS_AAAA_1); - jest.advanceTimersByTime(EXPIRATION_OFFSET_MS); + vi.advanceTimersByTime(EXPIRATION_OFFSET_MS); hostEntry.processRecords(); expect(hostEntry.aRecords.length).toEqual(0); expect(hostEntry.failedARecords.length).toEqual(1); diff --git a/packages/util-dns/src/util/HostEntryTable.spec.ts b/packages/util-dns/src/util/HostEntryTable.spec.ts index 67f233f0d42ad..ea64e9ec57134 100644 --- a/packages/util-dns/src/util/HostEntryTable.spec.ts +++ b/packages/util-dns/src/util/HostEntryTable.spec.ts @@ -1,4 +1,5 @@ import { HostResolverArguments } from "@aws-sdk/types"; +import { beforeEach, describe, expect, test as it } from "vitest"; import { HostEntryTable } from "./HostEntryTable"; diff --git a/packages/util-dns/vitest.config.ts b/packages/util-dns/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-dns/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-dynamodb/jest.config.js b/packages/util-dynamodb/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-dynamodb/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-dynamodb/package.json b/packages/util-dynamodb/package.json index 7070b9cdda849..7215196eddbcc 100644 --- a/packages/util-dynamodb/package.json +++ b/packages/util-dynamodb/package.json @@ -10,7 +10,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-dynamodb/src/NumberValue.spec.ts b/packages/util-dynamodb/src/NumberValue.spec.ts index c7e3b047d1aa2..dd26092b44240 100644 --- a/packages/util-dynamodb/src/NumberValue.spec.ts +++ b/packages/util-dynamodb/src/NumberValue.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { NumberValue } from "./NumberValue"; const BIG_DECIMAL = diff --git a/packages/util-dynamodb/src/convertToAttr.spec.ts b/packages/util-dynamodb/src/convertToAttr.spec.ts index eae38fb3efd19..4e236719afb37 100644 --- a/packages/util-dynamodb/src/convertToAttr.spec.ts +++ b/packages/util-dynamodb/src/convertToAttr.spec.ts @@ -2,6 +2,7 @@ * @jest-environment jsdom */ import { AttributeValue } from "@aws-sdk/client-dynamodb"; +import { describe, expect, test as it } from "vitest"; import { convertToAttr } from "./convertToAttr"; import { marshallOptions } from "./marshall"; diff --git a/packages/util-dynamodb/src/convertToAttrToNative.spec.ts b/packages/util-dynamodb/src/convertToAttrToNative.spec.ts index f9a2116eff150..4dad2c51ae9f0 100644 --- a/packages/util-dynamodb/src/convertToAttrToNative.spec.ts +++ b/packages/util-dynamodb/src/convertToAttrToNative.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + /** * @jest-environment jsdom */ diff --git a/packages/util-dynamodb/src/convertToNative.spec.ts b/packages/util-dynamodb/src/convertToNative.spec.ts index 386b19ba633b9..c235feae2eb06 100644 --- a/packages/util-dynamodb/src/convertToNative.spec.ts +++ b/packages/util-dynamodb/src/convertToNative.spec.ts @@ -1,4 +1,5 @@ import { AttributeValue } from "@aws-sdk/client-dynamodb"; +import { describe, expect, test as it } from "vitest"; import { convertToNative } from "./convertToNative"; import { NativeAttributeValue } from "./models"; diff --git a/packages/util-dynamodb/src/marshall.spec.ts b/packages/util-dynamodb/src/marshall.spec.ts index 9a1f784a43b56..546172834ee18 100644 --- a/packages/util-dynamodb/src/marshall.spec.ts +++ b/packages/util-dynamodb/src/marshall.spec.ts @@ -1,4 +1,5 @@ import { AttributeValue } from "@aws-sdk/client-dynamodb"; +import { describe, expect, test as it } from "vitest"; import { marshall } from "./marshall"; import { NumberValue } from "./NumberValue"; diff --git a/packages/util-dynamodb/src/marshallTypes.spec.ts b/packages/util-dynamodb/src/marshallTypes.spec.ts index c1bccde867ec9..b7985ae4b6e25 100644 --- a/packages/util-dynamodb/src/marshallTypes.spec.ts +++ b/packages/util-dynamodb/src/marshallTypes.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { convertToAttr } from "./convertToAttr"; import { marshall } from "./marshall"; diff --git a/packages/util-dynamodb/src/unmarshall.spec.ts b/packages/util-dynamodb/src/unmarshall.spec.ts index 7c74df3e9afe9..b7a2521dd4e5e 100644 --- a/packages/util-dynamodb/src/unmarshall.spec.ts +++ b/packages/util-dynamodb/src/unmarshall.spec.ts @@ -1,17 +1,19 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { convertToNative } from "./convertToNative"; import { unmarshall } from "./unmarshall"; -jest.mock("./convertToNative"); +vi.mock("./convertToNative"); describe("marshall", () => { const input = { a: "A" }; beforeEach(() => { - (convertToNative as jest.Mock).mockReturnValue(input); + vi.mocked(convertToNative).mockReturnValue(input); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("calls convertToNative", () => { diff --git a/packages/util-dynamodb/vitest.config.ts b/packages/util-dynamodb/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-dynamodb/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 d09aba7398c72..0000000000000 --- 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 a8d1c2e499123..0000000000000 --- 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 21cc3dcc91c8f..7838438d67cf0 100644 --- a/packages/util-endpoints/package.json +++ b/packages/util-endpoints/package.json @@ -13,8 +13,10 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest", - "test:integration": "jest --c jest.config.integ.js" + "test": "vitest run", + "test:integration": "vitest run -c vitest.config.integ.ts", + "test:watch": "vitest watch", + "test:integration:watch": "vitest watch -c vitest.config.integ.ts" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-endpoints/src/lib/aws/isVirtualHostableS3Bucket.spec.ts b/packages/util-endpoints/src/lib/aws/isVirtualHostableS3Bucket.spec.ts index dc637e7595e3a..11e2a9bd96367 100644 --- a/packages/util-endpoints/src/lib/aws/isVirtualHostableS3Bucket.spec.ts +++ b/packages/util-endpoints/src/lib/aws/isVirtualHostableS3Bucket.spec.ts @@ -1,25 +1,24 @@ -import { isValidHostLabel } from "@smithy/util-endpoints"; +import { isIpAddress, isValidHostLabel } from "@smithy/util-endpoints"; +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; -import { isIpAddress } from "../isIpAddress"; import { isVirtualHostableS3Bucket } from "./isVirtualHostableS3Bucket"; -jest.mock("../isIpAddress"); -jest.mock("@smithy/util-endpoints"); +vi.mock("@smithy/util-endpoints"); describe(isVirtualHostableS3Bucket.name, () => { const mockValue = "mockvalue"; beforeEach(() => { - (isIpAddress as jest.Mock).mockReturnValue(false); - (isValidHostLabel as jest.Mock).mockReturnValue(true); + vi.mocked(isIpAddress).mockReturnValue(false); + vi.mocked(isValidHostLabel).mockReturnValue(true); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("returns false if value is not a valid host label", () => { - (isValidHostLabel as jest.Mock).mockReturnValue(false); + vi.mocked(isValidHostLabel).mockReturnValue(false); expect(isVirtualHostableS3Bucket(mockValue)).toBe(false); expect(isValidHostLabel).toHaveBeenCalledWith(mockValue); expect(isIpAddress).not.toHaveBeenCalled(); @@ -47,7 +46,7 @@ describe(isVirtualHostableS3Bucket.name, () => { }); it("returns false if value is an IP address", () => { - (isIpAddress as jest.Mock).mockReturnValue(true); + vi.mocked(isIpAddress).mockReturnValue(true); expect(isVirtualHostableS3Bucket(mockValue)).toBe(false); expect(isValidHostLabel).toHaveBeenCalledWith(mockValue); expect(isIpAddress).toHaveBeenCalledWith(mockValue); @@ -80,8 +79,8 @@ describe(isVirtualHostableS3Bucket.name, () => { const mockValueWithSubdomain = `${mockValue}.${mockSubdomain}`; it("returns false if value is not a valid host label", () => { - (isValidHostLabel as jest.Mock).mockReturnValueOnce(true); - (isValidHostLabel as jest.Mock).mockReturnValueOnce(false); + vi.mocked(isValidHostLabel).mockReturnValueOnce(true); + vi.mocked(isValidHostLabel).mockReturnValueOnce(false); expect(isVirtualHostableS3Bucket(mockValueWithSubdomain, true)).toBe(false); expect(isValidHostLabel).toHaveBeenNthCalledWith(1, mockValue); @@ -104,8 +103,8 @@ describe(isVirtualHostableS3Bucket.name, () => { }); it("returns false if value is an IP address", () => { - (isIpAddress as jest.Mock).mockReturnValueOnce(false); - (isIpAddress as jest.Mock).mockReturnValueOnce(true); + vi.mocked(isIpAddress).mockReturnValueOnce(false); + vi.mocked(isIpAddress).mockReturnValueOnce(true); expect(isVirtualHostableS3Bucket(mockValueWithSubdomain, true)).toBe(false); expect(isIpAddress).toHaveBeenNthCalledWith(1, mockValue); diff --git a/packages/util-endpoints/src/lib/aws/parseArn.spec.ts b/packages/util-endpoints/src/lib/aws/parseArn.spec.ts index 16e0342dae985..1d1818d5b26c8 100644 --- a/packages/util-endpoints/src/lib/aws/parseArn.spec.ts +++ b/packages/util-endpoints/src/lib/aws/parseArn.spec.ts @@ -1,4 +1,5 @@ import { EndpointARN } from "@aws-sdk/types"; +import { describe, expect, test as it } from "vitest"; import { parseArn } from "./parseArn"; diff --git a/packages/util-endpoints/src/lib/aws/partition.spec.ts b/packages/util-endpoints/src/lib/aws/partition.spec.ts index 8afa60cd16d13..48996f8a76882 100644 --- a/packages/util-endpoints/src/lib/aws/partition.spec.ts +++ b/packages/util-endpoints/src/lib/aws/partition.spec.ts @@ -1,3 +1,5 @@ +import { afterEach, beforeEach, describe, expect, test as it } from "vitest"; + import { getUserAgentPrefix, partition, setPartitionInfo, useDefaultPartitionInfo } from "./partition"; const MOCK_DEFAULT_PARTITION = { diff --git a/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts b/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts index 49d381987052c..35e9448fb2236 100644 --- a/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts +++ b/packages/util-endpoints/src/resolveEndpoint.integ.spec.ts @@ -2,6 +2,7 @@ import "./aws"; 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"; @@ -25,7 +26,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/vitest.config.integ.ts b/packages/util-endpoints/vitest.config.integ.ts new file mode 100644 index 0000000000000..5802db1ac64a8 --- /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 0000000000000..4e46707824a58 --- /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-format-url/jest.config.js b/packages/util-format-url/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-format-url/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-format-url/package.json b/packages/util-format-url/package.json index 9f4e4cab21959..82dd626c9547c 100644 --- a/packages/util-format-url/package.json +++ b/packages/util-format-url/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-format-url/src/index.spec.ts b/packages/util-format-url/src/index.spec.ts index d564dbfb3fc95..04b659196f4dc 100644 --- a/packages/util-format-url/src/index.spec.ts +++ b/packages/util-format-url/src/index.spec.ts @@ -1,4 +1,5 @@ import { HttpRequest } from "@smithy/types"; +import { describe, expect, test as it } from "vitest"; import { formatUrl } from "./"; diff --git a/packages/util-format-url/vitest.config.ts b/packages/util-format-url/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-format-url/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-locate-window/jest.config.js b/packages/util-locate-window/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-locate-window/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/util-locate-window/package.json b/packages/util-locate-window/package.json index a31616371dea7..e0258207db962 100644 --- a/packages/util-locate-window/package.json +++ b/packages/util-locate-window/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/util-locate-window/src/index.spec.ts b/packages/util-locate-window/src/index.spec.ts index d147116b64ff4..3b13d3655513e 100644 --- a/packages/util-locate-window/src/index.spec.ts +++ b/packages/util-locate-window/src/index.spec.ts @@ -1,7 +1,8 @@ +import { afterEach, beforeEach, describe, expect, test as it } from "vitest"; + /** * @jest-environment node */ - import { locateWindow } from "./"; describe("locateWindow", () => { diff --git a/packages/util-locate-window/vitest.config.ts b/packages/util-locate-window/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-locate-window/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-user-agent-browser/jest.config.js b/packages/util-user-agent-browser/jest.config.js deleted file mode 100644 index bd895a5df03ec..0000000000000 --- a/packages/util-user-agent-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-user-agent-browser/package.json b/packages/util-user-agent-browser/package.json index 4b283987b74c2..350f5e1c2197c 100644 --- a/packages/util-user-agent-browser/package.json +++ b/packages/util-user-agent-browser/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-user-agent-browser/src/index.native.spec.ts b/packages/util-user-agent-browser/src/index.native.spec.ts index b7d60589d1160..fba0606d44689 100644 --- a/packages/util-user-agent-browser/src/index.native.spec.ts +++ b/packages/util-user-agent-browser/src/index.native.spec.ts @@ -1,9 +1,11 @@ +import { expect, test as it, vi } from "vitest"; + import { defaultUserAgent } from "./index.native"; it("should response basic browser default user agent", async () => { // RN doesn't have userAgent in window.navigator. //@ts-ignore mock no userAgent exists. - jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(undefined); + vi.spyOn(window.navigator, "userAgent", "get").mockReturnValue(undefined); const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })(); expect(userAgent[0]).toEqual(["aws-sdk-js", "0.1.0"]); expect(userAgent[1]).toEqual(["ua", "2.1"]); @@ -11,5 +13,5 @@ it("should response basic browser default user agent", async () => { expect(userAgent[3]).toEqual(["lang/js"]); expect(userAgent[4]).toEqual(["md/rn"]); expect(userAgent[5]).toEqual(["api/s3", "0.1.0"]); - jest.clearAllMocks(); + vi.clearAllMocks(); }); diff --git a/packages/util-user-agent-browser/src/index.spec.ts b/packages/util-user-agent-browser/src/index.spec.ts index 21a1d1c87e0ef..3aed1897137ca 100644 --- a/packages/util-user-agent-browser/src/index.spec.ts +++ b/packages/util-user-agent-browser/src/index.spec.ts @@ -1,19 +1,21 @@ +import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + import { createDefaultUserAgentProvider, PreviouslyResolved } from "."; const ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; const mockConfig: PreviouslyResolved = { - userAgentAppId: jest.fn().mockResolvedValue(undefined), + userAgentAppId: vi.fn().mockResolvedValue(undefined), }; describe("createDefaultUserAgentProvider", () => { beforeEach(() => { - jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(ua); + vi.spyOn(window.navigator, "userAgent", "get").mockReturnValue(ua); }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it("should populate metrics", async () => { @@ -37,7 +39,7 @@ describe("createDefaultUserAgentProvider", () => { it("should include appId when provided", async () => { const configWithAppId: PreviouslyResolved = { - userAgentAppId: jest.fn().mockResolvedValue("test-app-id"), + userAgentAppId: vi.fn().mockResolvedValue("test-app-id"), }; const userAgent = await createDefaultUserAgentProvider({ serviceId: "s3", clientVersion: "0.1.0" })( configWithAppId diff --git a/packages/util-user-agent-browser/vitest.config.ts b/packages/util-user-agent-browser/vitest.config.ts new file mode 100644 index 0000000000000..44808064872cb --- /dev/null +++ b/packages/util-user-agent-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/util-user-agent-node/jest.config.js b/packages/util-user-agent-node/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/util-user-agent-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-user-agent-node/package.json b/packages/util-user-agent-node/package.json index 04883fb187d07..9c9aa9b65d1cc 100644 --- a/packages/util-user-agent-node/package.json +++ b/packages/util-user-agent-node/package.json @@ -9,7 +9,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "main": "./dist-cjs/index.js", "module": "./dist-es/index.js", diff --git a/packages/util-user-agent-node/src/defaultUserAgent.spec.ts b/packages/util-user-agent-node/src/defaultUserAgent.spec.ts index 86c662588306b..72b15bfb2d2d5 100644 --- a/packages/util-user-agent-node/src/defaultUserAgent.spec.ts +++ b/packages/util-user-agent-node/src/defaultUserAgent.spec.ts @@ -1,40 +1,47 @@ -jest.mock("os", () => ({ +import process from "process"; +import { afterAll, afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; + +vi.mock("os", () => ({ platform: () => "darwin", release: () => "19.6.0", })); -const mockEnv = {}; - -jest.mock("process", () => ({ - env: mockEnv, - versions: { - node: "14.13.1", - }, -})); - +vi.mock("process", () => { + const pkg = { + env: {}, + versions: { + node: "14.13.1", + }, + }; + return { + ...pkg, + default: pkg, + }; +}); -jest.mock("./is-crt-available", () => ({ - isCrtAvailable: jest.fn().mockReturnValue(null), +vi.mock("./is-crt-available", () => ({ + isCrtAvailable: vi.fn().mockReturnValue(null), })); import { UserAgent } from "@smithy/types"; + import { createDefaultUserAgentProvider, PreviouslyResolved } from "./defaultUserAgent"; import { isCrtAvailable } from "./is-crt-available"; const validateUserAgent = (userAgent: UserAgent, expected: UserAgent) => { - expect(userAgent.length).toBe(expected.length); for (const pair of expected) { expect(userAgent).toContainEqual(pair); } + expect(userAgent.length).toBe(expected.length); }; describe("createDefaultUserAgentProvider", () => { beforeEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); afterAll(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); const basicUserAgent: UserAgent = [ @@ -47,7 +54,7 @@ describe("createDefaultUserAgentProvider", () => { ]; const mockConfig: PreviouslyResolved = { - userAgentAppId: jest.fn().mockResolvedValue(undefined), + userAgentAppId: vi.fn().mockResolvedValue(undefined), }; it("should return basic node default user agent", async () => { @@ -57,7 +64,7 @@ describe("createDefaultUserAgentProvider", () => { }); it("should set crt available key if aws-crt is available in runtime", async () => { - (isCrtAvailable as jest.Mock).mockReturnValue(["md/crt-avail"]); + vi.mocked(isCrtAvailable).mockReturnValue(["md/crt-avail"]); const userAgentProvider = createDefaultUserAgentProvider({ serviceId: "s3", clientVersion: "0.1.0" }); const userAgent = await userAgentProvider(mockConfig); expect(userAgent).toContainEqual(["md/crt-avail"]); @@ -72,21 +79,25 @@ describe("createDefaultUserAgentProvider", () => { ); }); - it("should add AWS_EXECUTION_ENV", async () => { - //@ts-ignore mock environmental variables - mockEnv.AWS_EXECUTION_ENV = "lambda"; - const userAgentProvider = createDefaultUserAgentProvider({ serviceId: "s3", clientVersion: "0.1.0" }); - const userAgent = await userAgentProvider(mockConfig); - const expectedUserAgent: UserAgent = [...basicUserAgent, ["exec-env/lambda"]]; - validateUserAgent(userAgent, expectedUserAgent); - //@ts-ignore mock environmental variables - delete mockEnv.AWS_EXECUTION_ENV; + describe("env", () => { + beforeEach(() => { + process.env.AWS_EXECUTION_ENV = "lambda"; + }); + afterEach(() => { + delete process.env.AWS_EXECUTION_ENV; + }); + it("should add AWS_EXECUTION_ENV", async () => { + const userAgentProvider = createDefaultUserAgentProvider({ serviceId: "s3", clientVersion: "0.1.0" }); + const userAgent = await userAgentProvider(mockConfig); + const expectedUserAgent: UserAgent = [...basicUserAgent, ["exec-env/lambda"]]; + validateUserAgent(userAgent, expectedUserAgent); + }); }); it("should add app id if available", async () => { const appId = "appId12345"; const configWithAppId: PreviouslyResolved = { - userAgentAppId: jest.fn().mockResolvedValue(appId), + userAgentAppId: vi.fn().mockResolvedValue(appId), }; const userAgentProvider = createDefaultUserAgentProvider({ serviceId: "s3", clientVersion: "0.1.0" }); const userAgent = await userAgentProvider(configWithAppId); diff --git a/packages/util-user-agent-node/vitest.config.ts b/packages/util-user-agent-node/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/util-user-agent-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/xhr-http-handler/jest.config.js b/packages/xhr-http-handler/jest.config.js deleted file mode 100644 index e29c0e8a0cde0..0000000000000 --- a/packages/xhr-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/xhr-http-handler/package.json b/packages/xhr-http-handler/package.json index fe8f7ef76a2dc..9d7383a45f4e8 100644 --- a/packages/xhr-http-handler/package.json +++ b/packages/xhr-http-handler/package.json @@ -11,7 +11,8 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", - "test": "jest --coverage" + "test": "vitest run", + "test:watch": "vitest watch" }, "author": "AWS SDK for JavaScript Team (https://aws.amazon.com/javascript/)", "license": "Apache-2.0", diff --git a/packages/xhr-http-handler/src/index.spec.ts b/packages/xhr-http-handler/src/index.spec.ts index 13baac33b5265..83f90a95b7710 100644 --- a/packages/xhr-http-handler/src/index.spec.ts +++ b/packages/xhr-http-handler/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { XhrHttpHandler } from "./index"; describe("index", () => { diff --git a/packages/xhr-http-handler/src/xhr-http-handler.spec.ts b/packages/xhr-http-handler/src/xhr-http-handler.spec.ts index 9bcf1399fc671..f37f0619746d8 100644 --- a/packages/xhr-http-handler/src/xhr-http-handler.spec.ts +++ b/packages/xhr-http-handler/src/xhr-http-handler.spec.ts @@ -1,5 +1,6 @@ import { AbortSignal } from "@smithy/abort-controller"; import { HttpRequest } from "@smithy/protocol-http"; +import { afterAll, afterEach, beforeAll, describe, expect, test as it, vi } from "vitest"; import { XhrHttpHandler } from "./xhr-http-handler"; @@ -57,7 +58,7 @@ describe(XhrHttpHandler.name, () => { public writable = { getWriter() { return { - releaseLock: jest.fn(), + releaseLock: vi.fn(), }; }, close() {}, diff --git a/packages/xhr-http-handler/vitest.config.ts b/packages/xhr-http-handler/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/xhr-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/xml-builder/jest.config.js b/packages/xml-builder/jest.config.js deleted file mode 100644 index a8d1c2e499123..0000000000000 --- a/packages/xml-builder/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require("../../jest.config.base.js"); - -module.exports = { - ...base, -}; diff --git a/packages/xml-builder/package.json b/packages/xml-builder/package.json index 22f9f68b29684..0653a80b4a206 100644 --- a/packages/xml-builder/package.json +++ b/packages/xml-builder/package.json @@ -14,7 +14,8 @@ "build:types": "tsc -p tsconfig.types.json", "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest watch" }, "author": { "name": "AWS SDK for JavaScript Team", diff --git a/packages/xml-builder/src/XmlNode.spec.ts b/packages/xml-builder/src/XmlNode.spec.ts index 16f2f0d9fc81f..4beab964c311b 100644 --- a/packages/xml-builder/src/XmlNode.spec.ts +++ b/packages/xml-builder/src/XmlNode.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { XmlNode } from "./XmlNode"; import { XmlText } from "./XmlText"; @@ -115,7 +117,7 @@ describe("XmlNode", () => { expect(node.toString()).toEqual("aaabbb"); }); }); - describe('.lc() "list with container"', () => { + it('.lc() "list with container"', () => { const data = { alist: [XmlNode.of("a", "aaa"), XmlNode.of("b", "bbb")] }; const node = new XmlNode("root"); diff --git a/packages/xml-builder/src/XmlText.spec.ts b/packages/xml-builder/src/XmlText.spec.ts index ecae4fce634c4..399625b09897f 100644 --- a/packages/xml-builder/src/XmlText.spec.ts +++ b/packages/xml-builder/src/XmlText.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { XmlText } from "./XmlText"; describe("XmlText", () => { diff --git a/packages/xml-builder/src/escape-attribute.spec.ts b/packages/xml-builder/src/escape-attribute.spec.ts index 2a70b0a97e370..91346d40bb40b 100644 --- a/packages/xml-builder/src/escape-attribute.spec.ts +++ b/packages/xml-builder/src/escape-attribute.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { escapeAttribute } from "./escape-attribute"; describe("escape-attribute", () => { diff --git a/packages/xml-builder/src/escape-element.spec.ts b/packages/xml-builder/src/escape-element.spec.ts index 5f660dfb6dafa..a7fbc8ca0cebc 100644 --- a/packages/xml-builder/src/escape-element.spec.ts +++ b/packages/xml-builder/src/escape-element.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { escapeElement } from "./escape-element"; describe("escape-element", () => { diff --git a/packages/xml-builder/src/index.spec.ts b/packages/xml-builder/src/index.spec.ts index 82e2596c3590b..28ea8778de087 100644 --- a/packages/xml-builder/src/index.spec.ts +++ b/packages/xml-builder/src/index.spec.ts @@ -1,3 +1,5 @@ +import { describe, expect, test as it } from "vitest"; + import { XmlNode, XmlText } from "./"; describe("package index", () => { diff --git a/packages/xml-builder/vitest.config.ts b/packages/xml-builder/vitest.config.ts new file mode 100644 index 0000000000000..4e46707824a58 --- /dev/null +++ b/packages/xml-builder/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/aws-restjson-server/package.json b/private/aws-restjson-server/package.json index 156487ec43327..c314bd7f011ab 100644 --- a/private/aws-restjson-server/package.json +++ b/private/aws-restjson-server/package.json @@ -11,7 +11,7 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "prepack": "yarn run clean && yarn run build", - "test": "jest --coverage --passWithNoTests" + "test": "jest" }, "main": "./dist-cjs/index.js", "types": "./dist-types/index.d.ts", diff --git a/private/aws-restjson-validation-server/package.json b/private/aws-restjson-validation-server/package.json index 7f5f737523b38..2623cef9dc95e 100644 --- a/private/aws-restjson-validation-server/package.json +++ b/private/aws-restjson-validation-server/package.json @@ -11,7 +11,7 @@ "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "prepack": "yarn run clean && yarn run build", - "test": "jest --coverage --passWithNoTests" + "test": "jest" }, "main": "./dist-cjs/index.js", "types": "./dist-types/index.d.ts", diff --git a/scripts/generate-clients/copy-to-clients.js b/scripts/generate-clients/copy-to-clients.js index 62221a20bded1..e0d291f69fea1 100644 --- a/scripts/generate-clients/copy-to-clients.js +++ b/scripts/generate-clients/copy-to-clients.js @@ -229,7 +229,7 @@ const copyServerTests = async (sourceDir, destinationDir) => { }, }; if (!mergedManifest.scripts.test) { - mergedManifest.scripts.test = "jest --coverage --passWithNoTests"; + mergedManifest.scripts.test = "jest"; } if (mergedManifest.private) { // don't generate documentation for private packages diff --git a/scripts/validation/vitest-validation.js b/scripts/validation/vitest-validation.js index 13c98f9741764..300590b6a94f7 100644 --- a/scripts/validation/vitest-validation.js +++ b/scripts/validation/vitest-validation.js @@ -3,6 +3,10 @@ const path = require("path"); const walk = require("../utils/walk"); const paths = [ + ...[...fs.readdirSync(path.join(__dirname, "..", "..", "..", "smithy-typescript", "packages"))].map((pkg) => { + return path.join(__dirname, "..", "..", "..", "smithy-typescript", "packages", pkg); + }), + // path.join(__dirname, "..", "..", "clients", "client-kinesis"), // path.join(__dirname, "..", "..", "clients", "client-s3"), // path.join(__dirname, "..", "..", "clients", "client-sts"), @@ -52,24 +56,47 @@ const paths = [ // path.join(__dirname, "..", "..", "packages", "middleware-token"), // path.join(__dirname, "..", "..", "packages", "middleware-user-agent"), // path.join(__dirname, "..", "..", "packages", "middleware-websocket"), + + // path.join(__dirname, "..", "..", "packages", "polly-request-presigner"), + // path.join(__dirname, "..", "..", "packages", "rds-signer"), + // path.join(__dirname, "..", "..", "packages", "region-config-resolver"), // path.join(__dirname, "..", "..", "packages", "s3-presigned-post"), - path.join(__dirname, "..", "..", "private", "aws-middleware-test"), - path.join(__dirname, "..", "..", "private", "aws-util-test"), - path.join(__dirname, "..", "..", "private", "aws-client-api-test"), - path.join(__dirname, "..", "..", "private", "aws-client-retry-test"), - path.join(__dirname, "..", "..", "private", "aws-echo-service"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-ec2"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-json"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-json-10"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-json-machinelearning"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-query"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson-apigateway"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson-glacier"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-restxml"), - path.join(__dirname, "..", "..", "private", "aws-protocoltests-smithy-rpcv2-cbor"), - path.join(__dirname, "..", "..", "private", "aws-restjson-server"), - path.join(__dirname, "..", "..", "private", "aws-restjson-validation-server"), + // path.join(__dirname, "..", "..", "packages", "s3-request-presigner"), + // path.join(__dirname, "..", "..", "packages", "sha256-tree-hash"), + // path.join(__dirname, "..", "..", "packages", "signature-v4-crt"), + // path.join(__dirname, "..", "..", "packages", "signature-v4-multi-region"), + // path.join(__dirname, "..", "..", "packages", "smithy-client"), + // path.join(__dirname, "..", "..", "packages", "token-providers"), + // path.join(__dirname, "..", "..", "packages", "types"), + // path.join(__dirname, "..", "..", "packages", "util-arn-parser"), + // path.join(__dirname, "..", "..", "packages", "util-create-request"), + // path.join(__dirname, "..", "..", "packages", "util-dns"), + // path.join(__dirname, "..", "..", "packages", "util-dynamodb"), + // path.join(__dirname, "..", "..", "packages", "util-endpoints"), + // path.join(__dirname, "..", "..", "packages", "util-format-url"), + // path.join(__dirname, "..", "..", "packages", "util-locate-window"), + // path.join(__dirname, "..", "..", "packages", "util-user-agent-browser"), + // path.join(__dirname, "..", "..", "packages", "util-user-agent-node"), + // path.join(__dirname, "..", "..", "packages", "xhr-http-handler"), + // path.join(__dirname, "..", "..", "packages", "xml-builder"), + + // path.join(__dirname, "..", "..", "private", "aws-middleware-test"), + // path.join(__dirname, "..", "..", "private", "aws-util-test"), + // path.join(__dirname, "..", "..", "private", "aws-client-api-test"), + // path.join(__dirname, "..", "..", "private", "aws-client-retry-test"), + // path.join(__dirname, "..", "..", "private", "aws-echo-service"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-ec2"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-json"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-json-10"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-json-machinelearning"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-query"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson-apigateway"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-restjson-glacier"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-restxml"), + // path.join(__dirname, "..", "..", "private", "aws-protocoltests-smithy-rpcv2-cbor"), + // path.join(__dirname, "..", "..", "private", "aws-restjson-server"), + // path.join(__dirname, "..", "..", "private", "aws-restjson-validation-server"), ]; (async () => { diff --git a/vitest.config.e2e.ts b/vitest.config.e2e.ts index eff43a280d0a1..d035dcc4e5078 100644 --- a/vitest.config.e2e.ts +++ b/vitest.config.e2e.ts @@ -2,7 +2,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { - exclude: ["**/*.browser.e2e.spec.ts"], + exclude: ["node_modules", "**/*.browser.e2e.spec.ts"], include: ["**/*.e2e.spec.ts"], environment: "node", }, diff --git a/vitest.config.integ.ts b/vitest.config.integ.ts index cdec52abaf642..b25e8e1dcb00b 100644 --- a/vitest.config.integ.ts +++ b/vitest.config.integ.ts @@ -2,7 +2,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { - exclude: ["**/*.{e2e,browser}.spec.ts"], + exclude: ["node_modules", "**/*.{e2e,browser}.spec.ts"], include: ["{clients,lib,packages,private}/**/*.integ.spec.ts"], environment: "node", }, diff --git a/vitest.config.ts b/vitest.config.ts index e35b9249e8216..22114730664a9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { exclude: [ + "node_modules", "**/*.{integ,e2e,browser}.spec.ts", "private/aws-restjson-server/**/*.spec.ts", "private/aws-restjson-validation-server/**/*.spec.ts", From ef600c1a0a1c44a38658e7a267312f0133898b90 Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 24 Oct 2024 17:04:15 +0000 Subject: [PATCH 2/2] test: remove karma --- packages/xhr-http-handler/karma.conf.js | 26 ---------------------- packages/xhr-http-handler/vitest.config.ts | 2 +- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 packages/xhr-http-handler/karma.conf.js diff --git a/packages/xhr-http-handler/karma.conf.js b/packages/xhr-http-handler/karma.conf.js deleted file mode 100644 index 5d5e7447a403b..0000000000000 --- a/packages/xhr-http-handler/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/xhr-http-handler.ts", "src/xhr-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: false, - }, - }, - singleRun: true, - }); -}; diff --git a/packages/xhr-http-handler/vitest.config.ts b/packages/xhr-http-handler/vitest.config.ts index 4e46707824a58..73fcc11c3178c 100644 --- a/packages/xhr-http-handler/vitest.config.ts +++ b/packages/xhr-http-handler/vitest.config.ts @@ -4,6 +4,6 @@ export default defineConfig({ test: { exclude: ["**/*.{integ,e2e,browser}.spec.ts"], include: ["**/*.spec.ts"], - environment: "node", + environment: "happy-dom", }, });