From 7e54da56e2d6507f75306f9089b8ba3f760d7510 Mon Sep 17 00:00:00 2001 From: Robbie Ginsburg Date: Wed, 25 Sep 2024 13:15:26 -0400 Subject: [PATCH 1/4] first batch of sinon to jest --- lib/msal-common/package.json | 2 - .../test/cache/CacheManager.spec.ts | 75 ++++---- .../test/cache/entities/AccountEntity.spec.ts | 68 +++---- .../test/client/BaseClient.spec.ts | 47 +++-- .../test/crypto/PopTokenGenerator.spec.ts | 23 ++- lib/msal-common/test/logger/Logger.spec.ts | 169 ++++++++++++------ .../test/network/NetworkManager.spec.ts | 147 ++++++++------- .../test/network/ThrottlingUtils.spec.ts | 85 ++++----- .../request/RequestParameterBuilder.spec.ts | 40 ++--- lib/msal-common/test/request/ScopeSet.spec.ts | 29 ++- .../telemetry/ServerTelemetryManager.spec.ts | 36 ++-- lib/msal-common/test/url/UrlString.spec.ts | 21 +-- .../test/utils/ProtocolUtils.spec.ts | 13 +- package-lock.json | 2 - 14 files changed, 417 insertions(+), 340 deletions(-) diff --git a/lib/msal-common/package.json b/lib/msal-common/package.json index a96cace042..439ea346f6 100644 --- a/lib/msal-common/package.json +++ b/lib/msal-common/package.json @@ -107,7 +107,6 @@ "@types/jest": "^29.5.0", "@types/lodash": "^4.14.182", "@types/node": "^20.3.1", - "@types/sinon": "^7.5.0", "eslint-config-msal": "file:../../shared-configs/eslint-config-msal", "jest": "^29.5.0", "lodash": "^4.17.21", @@ -117,7 +116,6 @@ "rollup": "^3.29.5", "rollup-msal": "file:../../shared-configs/rollup-msal", "shx": "^0.3.2", - "sinon": "^7.5.0", "ts-jest": "^29.1.0", "ts-jest-resolver": "^2.0.1", "ts-node": "^10.9.1", diff --git a/lib/msal-common/test/cache/CacheManager.spec.ts b/lib/msal-common/test/cache/CacheManager.spec.ts index 0142b59af5..baa6853cfd 100644 --- a/lib/msal-common/test/cache/CacheManager.spec.ts +++ b/lib/msal-common/test/cache/CacheManager.spec.ts @@ -6,12 +6,11 @@ import { AuthenticationScheme, CredentialType, -} from "../../src/utils/Constants"; -import { AccountEntity } from "../../src/cache/entities/AccountEntity"; -import { AccessTokenEntity } from "../../src/cache/entities/AccessTokenEntity"; -import { CacheRecord } from "../../src/cache/entities/CacheRecord"; -import { AccountFilter } from "../../src/cache/utils/CacheTypes"; -import sinon from "sinon"; +} from "../../src/utils/Constants.js"; +import { AccountEntity } from "../../src/cache/entities/AccountEntity.js"; +import { AccessTokenEntity } from "../../src/cache/entities/AccessTokenEntity.js"; +import { CacheRecord } from "../../src/cache/entities/CacheRecord.js"; +import { AccountFilter } from "../../src/cache/utils/CacheTypes.js"; import { TEST_CONFIG, TEST_TOKENS, @@ -24,29 +23,29 @@ import { TEST_TOKEN_LIFETIMES, ID_TOKEN_ALT_CLAIMS, GUEST_ID_TOKEN_CLAIMS, -} from "../test_kit/StringConstants"; +} from "../test_kit/StringConstants.js"; import { ClientAuthErrorCodes, createClientAuthError, -} from "../../src/error/ClientAuthError"; -import { AccountInfo } from "../../src/account/AccountInfo"; -import { MockCache } from "./MockCache"; +} from "../../src/error/ClientAuthError.js"; +import { AccountInfo } from "../../src/account/AccountInfo.js"; +import { MockCache } from "./MockCache.js"; import { buildAccountFromIdTokenClaims, buildIdToken } from "msal-test-utils"; -import { mockCrypto } from "../client/ClientTestUtils"; -import { TestError } from "../test_kit/TestErrors"; -import { CacheManager } from "../../src/cache/CacheManager"; -import { AuthorityMetadataEntity } from "../../src/cache/entities/AuthorityMetadataEntity"; -import { AppMetadataEntity } from "../../src/cache/entities/AppMetadataEntity"; -import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity"; -import { IdTokenEntity } from "../../src/cache/entities/IdTokenEntity"; +import { mockCrypto } from "../client/ClientTestUtils.js"; +import { TestError } from "../test_kit/TestErrors.js"; +import { CacheManager } from "../../src/cache/CacheManager.js"; +import { AuthorityMetadataEntity } from "../../src/cache/entities/AuthorityMetadataEntity.js"; +import { AppMetadataEntity } from "../../src/cache/entities/AppMetadataEntity.js"; +import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity.js"; +import { IdTokenEntity } from "../../src/cache/entities/IdTokenEntity.js"; import { CacheHelpers, CommonSilentFlowRequest, PerformanceEvents, ScopeSet, -} from "../../src"; -import * as authorityMetadata from "../../src/authority/AuthorityMetadata"; -import { MockPerformanceClient } from "../telemetry/PerformanceClient.spec"; +} from "../../src/index.js"; +import * as authorityMetadata from "../../src/authority/AuthorityMetadata.js"; +import { MockPerformanceClient } from "../telemetry/PerformanceClient.spec.js"; describe("CacheManager.ts test cases", () => { const mockCache = new MockCache(CACHE_MOCKS.MOCK_CLIENT_ID, mockCrypto, { @@ -55,12 +54,12 @@ describe("CacheManager.ts test cases", () => { .metadata, knownAuthorities: [TEST_CONFIG.validAuthorityHost], }); - let authorityMetadataStub: sinon.SinonStub; + let authorityMetadataStub: jest.SpyInstance; beforeEach(() => { mockCache.initializeCache(); - authorityMetadataStub = sinon - .stub(CacheManager.prototype, "getAuthorityMetadataByAlias") - .callsFake((host) => { + authorityMetadataStub = jest + .spyOn(CacheManager.prototype, "getAuthorityMetadataByAlias") + .mockImplementation((host) => { const authorityMetadata: AuthorityMetadataEntity = { aliases: [host], preferred_cache: host, @@ -82,7 +81,7 @@ describe("CacheManager.ts test cases", () => { afterEach(async () => { await mockCache.clearCache(); - sinon.restore(); + jest.restoreAllMocks(); }); describe("saveCacheRecord tests", () => { @@ -767,7 +766,7 @@ describe("CacheManager.ts test cases", () => { mockCache.cacheManager.getAccountsFilteredBy(successFilter); // Both cached accounts have environments that are aliases of eachother, expect both to match expect(Object.keys(accounts).length).toEqual(2); - sinon.restore(); + jest.restoreAllMocks(); const wrongFilter: AccountFilter = { environment: "Wrong Env" }; accounts = @@ -807,7 +806,7 @@ describe("CacheManager.ts test cases", () => { }); describe("isCredentialKey", () => { - it("Returns false if key doesn't contain enough '-' deliniated sections", () => { + it("Returns false if key does not contain enough '-' deliniated sections", () => { expect( mockCache.cacheManager.isCredentialKey( "clientid-idToken-homeId" @@ -815,7 +814,7 @@ describe("CacheManager.ts test cases", () => { ).toBe(false); }); - it("Returns false if key doesn't contain a valid credential type", () => { + it("Returns false if key does not contain a valid credential type", () => { expect( mockCache.cacheManager.isCredentialKey( `homeAccountId-environment-credentialType-${CACHE_MOCKS.MOCK_CLIENT_ID}-realm-target-requestedClaimsHash-scheme` @@ -823,7 +822,7 @@ describe("CacheManager.ts test cases", () => { ).toBe(false); }); - it("Returns false if key doesn't contain clientId", () => { + it("Returns false if key does not contain clientId", () => { expect( mockCache.cacheManager.isCredentialKey( `homeAccountId-environment-accessToken-clientId-realm-target-requestedClaimsHash-scheme` @@ -1002,7 +1001,7 @@ describe("CacheManager.ts test cases", () => { ).mockReturnValueOnce(null); }); - it("ID token matches when filter contains it's own environment", () => { + it("ID token matches when filter contains its own environment", () => { // filter by environment expect( mockCache.cacheManager.credentialMatchesFilter( @@ -1014,7 +1013,7 @@ describe("CacheManager.ts test cases", () => { ).toBe(true); }); - it("Access token matches when filter contains it's own enviroment", () => { + it("Access token matches when filter contains its own enviroment", () => { expect( mockCache.cacheManager.credentialMatchesFilter( testAccessToken, @@ -1025,7 +1024,7 @@ describe("CacheManager.ts test cases", () => { ).toBe(true); }); - it("Refresh token matches when filter contains it's own environment", () => { + it("Refresh token matches when filter contains its own environment", () => { expect( mockCache.cacheManager.credentialMatchesFilter( testRefreshToken, @@ -1593,7 +1592,7 @@ describe("CacheManager.ts test cases", () => { tokenType: AuthenticationScheme.POP, }; - const removeTokenBindingKeySpy = sinon.spy( + const removeTokenBindingKeySpy = jest.spyOn( mockCrypto, "removeTokenBindingKey" ); @@ -1603,7 +1602,7 @@ describe("CacheManager.ts test cases", () => { ); const atKey = CacheHelpers.generateCredentialKey(atWithAuthScheme); expect(mockCache.cacheManager.getAccount(atKey)).toBeNull(); - expect(removeTokenBindingKeySpy.getCall(0).args[0]).toEqual( + expect(removeTokenBindingKeySpy.mock.calls[0][0]).toEqual( atWithAuthScheme.keyId ); }); @@ -1624,7 +1623,7 @@ describe("CacheManager.ts test cases", () => { tokenType: AuthenticationScheme.SSH, }; - const removeTokenBindingKeySpy = sinon.spy( + const removeTokenBindingKeySpy = jest.spyOn( mockCrypto, "removeTokenBindingKey" ); @@ -1634,10 +1633,10 @@ describe("CacheManager.ts test cases", () => { ); const atKey = CacheHelpers.generateCredentialKey(atWithAuthScheme); expect(mockCache.cacheManager.getAccount(atKey)).toBeNull(); - expect(removeTokenBindingKeySpy.callCount).toEqual(0); + expect(removeTokenBindingKeySpy).toHaveBeenCalledTimes(0); }); - it("throws bindingKeyNotRemoved error when key isn't deleted from storage", async () => { + it("throws bindingKeyNotRemoved error when key is not deleted from storage", async () => { const atWithAuthScheme = { environment: "login.microsoftonline.com", credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, @@ -2207,7 +2206,7 @@ describe("CacheManager.ts test cases", () => { }); it("getRefreshToken with environment aliases", () => { - authorityMetadataStub.callsFake((host) => { + authorityMetadataStub.mockImplementation((host) => { const authorityMetadata: AuthorityMetadataEntity = { aliases: ["login.microsoftonline.com", "login.windows.net"], preferred_cache: host, diff --git a/lib/msal-common/test/cache/entities/AccountEntity.spec.ts b/lib/msal-common/test/cache/entities/AccountEntity.spec.ts index 0dbe7110e8..fe03c29e18 100644 --- a/lib/msal-common/test/cache/entities/AccountEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/AccountEntity.spec.ts @@ -1,12 +1,12 @@ -import { AccountEntity } from "../../../src/cache/entities/AccountEntity"; -import { mockAccountEntity, mockIdTokenEntity } from "./cacheConstants"; -import * as AuthToken from "../../../src/account/AuthToken"; -import { CacheAccountType, Constants } from "../../../src/utils/Constants"; +import { AccountEntity } from "../../../src/cache/entities/AccountEntity.js"; +import { mockAccountEntity, mockIdTokenEntity } from "./cacheConstants.js"; +import * as AuthToken from "../../../src/account/AuthToken.js"; +import { CacheAccountType, Constants } from "../../../src/utils/Constants.js"; import { NetworkRequestOptions, INetworkModule, -} from "../../../src/network/INetworkModule"; -import { ICrypto } from "../../../src/crypto/ICrypto"; +} from "../../../src/network/INetworkModule.js"; +import { ICrypto } from "../../../src/crypto/ICrypto.js"; import { RANDOM_TEST_GUID, TEST_DATA_CLIENT_INFO, @@ -18,16 +18,18 @@ import { ID_TOKEN_CLAIMS, GUEST_ID_TOKEN_CLAIMS, TEST_CONFIG, -} from "../../test_kit/StringConstants"; -import sinon from "sinon"; -import { MockStorageClass, mockCrypto } from "../../client/ClientTestUtils"; -import { AccountInfo, TenantProfile } from "../../../src/account/AccountInfo"; -import { AuthorityOptions } from "../../../src/authority/AuthorityOptions"; -import { ProtocolMode } from "../../../src/authority/ProtocolMode"; -import { LogLevel, Logger } from "../../../src/logger/Logger"; -import { Authority } from "../../../src/authority/Authority"; -import { AuthorityType } from "../../../src/authority/AuthorityType"; -import { TokenClaims } from "../../../src"; +} from "../../test_kit/StringConstants.js"; +import { MockStorageClass, mockCrypto } from "../../client/ClientTestUtils.js"; +import { + AccountInfo, + TenantProfile, +} from "../../../src/account/AccountInfo.js"; +import { AuthorityOptions } from "../../../src/authority/AuthorityOptions.js"; +import { ProtocolMode } from "../../../src/authority/ProtocolMode.js"; +import { LogLevel, Logger } from "../../../src/logger/Logger.js"; +import { Authority } from "../../../src/authority/Authority.js"; +import { AuthorityType } from "../../../src/authority/AuthorityType.js"; +import { TokenClaims } from "../../../src/index.js"; import { buildAccountFromIdTokenClaims } from "msal-test-utils"; const cryptoInterface: ICrypto = { @@ -131,13 +133,13 @@ const authority = new Authority( describe("AccountEntity.ts Unit Tests", () => { beforeEach(() => { - sinon - .stub(Authority.prototype, "getPreferredCache") - .returns("login.windows.net"); + jest.spyOn(Authority.prototype, "getPreferredCache").mockReturnValue( + "login.windows.net" + ); }); afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("Verify an AccountEntity", () => { @@ -344,7 +346,9 @@ describe("AccountEntity.ts Unit Tests", () => { nonce: "123523", upn: "testupn", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const homeAccountId = "AAAAAAAAAAAAAAAAAAAAAIkzqFVrSaSaFHy782bbtaQ".toLowerCase(); @@ -396,7 +400,7 @@ describe("AccountEntity.ts Unit Tests", () => { expect(accountInfo.tenantProfiles).toMatchObject(tenantProfiles); }); - it("getAccountInfo creates a new tenantProfiles map if AccountEntity doesn't have a tenantProfiles array", () => { + it("getAccountInfo creates a new tenantProfiles map if AccountEntity does not have a tenantProfiles array", () => { const accountEntity = buildAccountFromIdTokenClaims(ID_TOKEN_CLAIMS); accountEntity.tenantProfiles = undefined; @@ -408,7 +412,7 @@ describe("AccountEntity.ts Unit Tests", () => { ); }); - it("isSingleTenant returns true if AccountEntity doesn't have a tenantProfiles array", () => { + it("isSingleTenant returns true if AccountEntity does not have a tenantProfiles array", () => { const accountEntity = buildAccountFromIdTokenClaims(ID_TOKEN_CLAIMS); accountEntity.tenantProfiles = undefined; @@ -638,13 +642,9 @@ describe("AccountEntity.ts Unit Tests", () => { describe("AccountEntity.ts Unit Tests for ADFS", () => { beforeEach(() => { - sinon - .stub(Authority.prototype, "getPreferredCache") - .returns("myadfs.com"); - }); - - afterEach(() => { - sinon.restore(); + jest.spyOn(Authority.prototype, "getPreferredCache").mockReturnValue( + "myadfs.com" + ); }); it("creates a generic ADFS account", () => { @@ -674,7 +674,9 @@ describe("AccountEntity.ts Unit Tests for ADFS", () => { nonce: "123523", upn: "testupn", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const homeAccountId = "AAAAAAAAAAAAAAAAAAAAAIkzqFVrSaSaFHy782bbtaQ".toLowerCase(); @@ -727,7 +729,9 @@ describe("AccountEntity.ts Unit Tests for ADFS", () => { nonce: "123523", upn: "testupn", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const homeAccountId = "AAAAAAAAAAAAAAAAAAAAAIkzqFVrSaSaFHy782bbtaQ".toLowerCase(); diff --git a/lib/msal-common/test/client/BaseClient.spec.ts b/lib/msal-common/test/client/BaseClient.spec.ts index 6c1af7443b..0c251bc902 100644 --- a/lib/msal-common/test/client/BaseClient.spec.ts +++ b/lib/msal-common/test/client/BaseClient.spec.ts @@ -1,10 +1,9 @@ -import { BaseClient } from "../../src/client/BaseClient"; -import { HeaderNames, Constants } from "../../src/utils/Constants"; -import { ClientTestUtils } from "./ClientTestUtils"; -import { ClientConfiguration } from "../../src/config/ClientConfiguration"; -import { DEFAULT_OPENID_CONFIG_RESPONSE } from "../test_kit/StringConstants"; -import { Authority } from "../../src/authority/Authority"; -import sinon from "sinon"; +import { BaseClient } from "../../src/client/BaseClient.js"; +import { HeaderNames, Constants } from "../../src/utils/Constants.js"; +import { ClientTestUtils } from "./ClientTestUtils.js"; +import { ClientConfiguration } from "../../src/config/ClientConfiguration.js"; +import { DEFAULT_OPENID_CONFIG_RESPONSE } from "../test_kit/StringConstants.js"; +import { Authority } from "../../src/authority/Authority.js"; class TestClient extends BaseClient { constructor(config: ClientConfiguration) { @@ -38,17 +37,15 @@ class TestClient extends BaseClient { describe("BaseClient.ts Class Unit Tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); describe("Constructor", () => { it("Creates a valid BaseClient object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new TestClient(config); @@ -57,12 +54,10 @@ describe("BaseClient.ts Class Unit Tests", () => { }); it("Sets fields on BaseClient object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new TestClient(config); @@ -76,16 +71,14 @@ describe("BaseClient.ts Class Unit Tests", () => { describe("Header utils", () => { beforeEach(() => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); }); afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("Creates default token request headers", async () => { diff --git a/lib/msal-common/test/crypto/PopTokenGenerator.spec.ts b/lib/msal-common/test/crypto/PopTokenGenerator.spec.ts index 5da3167022..c7906b2b10 100644 --- a/lib/msal-common/test/crypto/PopTokenGenerator.spec.ts +++ b/lib/msal-common/test/crypto/PopTokenGenerator.spec.ts @@ -1,4 +1,3 @@ -import sinon from "sinon"; import { RANDOM_TEST_GUID, TEST_POP_VALUES, @@ -6,19 +5,19 @@ import { TEST_CONFIG, TEST_URIS, TEST_CRYPTO_VALUES, -} from "../test_kit/StringConstants"; -import { PopTokenGenerator } from "../../src/crypto/PopTokenGenerator"; -import { ICrypto } from "../../src/crypto/ICrypto"; -import { BaseAuthRequest } from "../../src/request/BaseAuthRequest"; -import * as TimeUtils from "../../src/utils/TimeUtils"; -import { UrlString } from "../../src/url/UrlString"; -import { AuthenticationScheme } from "../../src/utils/Constants"; -import { SignedHttpRequest } from "../../src/crypto/SignedHttpRequest"; -import { Logger } from "../../src/logger/Logger"; +} from "../test_kit/StringConstants.js"; +import { PopTokenGenerator } from "../../src/crypto/PopTokenGenerator.js"; +import { ICrypto } from "../../src/crypto/ICrypto.js"; +import { BaseAuthRequest } from "../../src/request/BaseAuthRequest.js"; +import * as TimeUtils from "../../src/utils/TimeUtils.js"; +import { UrlString } from "../../src/url/UrlString.js"; +import { AuthenticationScheme } from "../../src/utils/Constants.js"; +import { SignedHttpRequest } from "../../src/crypto/SignedHttpRequest.js"; +import { Logger } from "../../src/logger/Logger.js"; describe("PopTokenGenerator Unit Tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); const cryptoInterface: ICrypto = { @@ -120,7 +119,7 @@ describe("PopTokenGenerator Unit Tests", () => { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, correlationId: TEST_CONFIG.CORRELATION_ID, }; - sinon.stub(TimeUtils, "nowSeconds").returns(currTime); + jest.spyOn(TimeUtils, "nowSeconds").mockReturnValue(currTime); }); it("Signs the proof-of-possession JWT token with all PoP parameters in the request", (done) => { diff --git a/lib/msal-common/test/logger/Logger.spec.ts b/lib/msal-common/test/logger/Logger.spec.ts index 3527b3e7c2..a711e7810c 100644 --- a/lib/msal-common/test/logger/Logger.spec.ts +++ b/lib/msal-common/test/logger/Logger.spec.ts @@ -1,10 +1,15 @@ -import { LoggerOptions } from "../../src/config/ClientConfiguration"; -import { LogLevel, Logger } from "../../src/logger/Logger"; -import sinon from "sinon"; +import { LoggerOptions } from "../../src/config/ClientConfiguration.js"; +import { LogLevel, Logger } from "../../src/logger/Logger.js"; describe("Logger.ts Class Unit Tests", () => { let loggerOptions: LoggerOptions; - let logStore = {}; + let logStore: { + [LogLevel.Error]?: string; + [LogLevel.Warning]?: string; + [LogLevel.Info]?: string; + [LogLevel.Verbose]?: string; + [LogLevel.Trace]?: string; + } = {}; beforeEach(() => { loggerOptions = { loggerCallback: ( @@ -21,7 +26,7 @@ describe("Logger.ts Class Unit Tests", () => { afterEach(() => { logStore = {}; - sinon.restore(); + jest.restoreAllMocks(); }); describe("Constructor and Getters", () => { @@ -105,7 +110,7 @@ describe("Logger.ts Class Unit Tests", () => { expect(logStore[LogLevel.Trace]).toBeTruthy(); }); - it("Creates a logger with level Info if logLevel isn't passed in", () => { + it("Creates a logger with level Info if logLevel is not passed in", () => { loggerOptions = { loggerCallback: ( level: LogLevel, @@ -221,11 +226,9 @@ describe("Logger.ts Class Unit Tests", () => { const logger = new Logger(loggerOptions); const loggerClone = logger.clone("msal-common", "2.0.0"); loggerClone.info("Message"); - expect(logStore[LogLevel.Info].includes("msal-common")).toBe(true); - expect(logStore[LogLevel.Info].includes("2.0.0")).toBe(true); - expect(logStore[LogLevel.Info].includes("msal-common@2.0.0")).toBe( - true - ); + expect(logStore[LogLevel.Info]).toContain("msal-common"); + expect(logStore[LogLevel.Info]).toContain("2.0.0"); + expect(logStore[LogLevel.Info]).toContain("msal-common@2.0.0"); }); }); @@ -242,11 +245,9 @@ describe("Logger.ts Class Unit Tests", () => { const logger = new Logger(loggerOptions); const loggerClone = logger.clone("msal-common", "2.0.0"); loggerClone.info("Message"); - expect(logStore[LogLevel.Info].includes("msal-common")).toBe(true); - expect(logStore[LogLevel.Info].includes("2.0.0")).toBe(true); - expect(logStore[LogLevel.Info].includes("msal-common@2.0.0")).toBe( - true - ); + expect(logStore[LogLevel.Info]).toContain("msal-common"); + expect(logStore[LogLevel.Info]).toContain("2.0.0"); + expect(logStore[LogLevel.Info]).toContain("msal-common@2.0.0"); }); }); @@ -260,109 +261,177 @@ describe("Logger.ts Class Unit Tests", () => { describe("Error APIs", () => { it("Executes error APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.error("Message"); - expect(executeCbSpy.calledWith(LogLevel.Error)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Error, + expect.anything(), + expect.anything() + ); }); it("Executes errorPii APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.errorPii("Message"); - expect(executeCbSpy.calledWith(LogLevel.Error)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Error, + expect.anything(), + expect.anything() + ); }); it("Does not execute errorPii APIs if piiLogging is disabled", () => { loggerOptions.piiLoggingEnabled = false; - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.errorPii("Message"); - expect(executeCbSpy.called).toBe(false); + expect(executeCbSpy).not.toHaveBeenCalled(); }); }); describe("Warning APIs", () => { it("Executes warning APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.warning("Message"); - expect(executeCbSpy.calledWith(LogLevel.Warning)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Warning, + expect.anything(), + expect.anything() + ); }); it("Executes warningPii APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.warningPii("Message"); - expect(executeCbSpy.calledWith(LogLevel.Warning)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Warning, + expect.anything(), + expect.anything() + ); }); it("Does not execute warningPii APIs if piiLogging is disabled", () => { loggerOptions.piiLoggingEnabled = false; - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.warningPii("Message"); - expect(executeCbSpy.called).toBe(false); + expect(executeCbSpy).not.toHaveBeenCalled(); }); }); describe("Info APIs", () => { it("Executes info APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.info("Message"); - expect(executeCbSpy.calledWith(LogLevel.Info)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Info, + expect.anything(), + expect.anything() + ); }); it("Executes infoPii APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.infoPii("Message"); - expect(executeCbSpy.calledWith(LogLevel.Info)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Info, + expect.anything(), + expect.anything() + ); }); it("Does not execute infoPii APIs if piiLogging is disabled", () => { loggerOptions.piiLoggingEnabled = false; - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.infoPii("Message"); - expect(executeCbSpy.called).toBe(false); + expect(executeCbSpy).not.toHaveBeenCalled(); }); }); describe("Verbose APIs", () => { it("Executes verbose APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.verbose("Message"); - expect(executeCbSpy.calledWith(LogLevel.Verbose)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Verbose, + expect.anything(), + expect.anything() + ); }); it("Executes verbosePii APIs", () => { - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.verbosePii("Message"); - expect(executeCbSpy.calledWith(LogLevel.Verbose)).toBe(true); + expect(executeCbSpy).toHaveBeenCalledWith( + LogLevel.Verbose, + expect.anything(), + expect.anything() + ); }); it("Does not execute verbosePii APIs if piiLogging is disabled", () => { loggerOptions.piiLoggingEnabled = false; - const executeCbSpy = sinon.spy(Logger.prototype, "executeCallback"); + const executeCbSpy = jest.spyOn( + Logger.prototype, + "executeCallback" + ); const logger = new Logger(loggerOptions); logger.verbosePii("Message"); - expect(executeCbSpy.called).toBe(false); + expect(executeCbSpy).not.toHaveBeenCalled(); }); }); @@ -375,9 +444,7 @@ describe("Logger.ts Class Unit Tests", () => { }); logger.verbose("Message"); - expect(logStore[LogLevel.Verbose].includes(testCorrelationId)).toBe( - true - ); + expect(logStore[LogLevel.Verbose]).toContain(testCorrelationId); }); it("CorrelationId is included in log message if passed in log message", () => { @@ -385,9 +452,7 @@ describe("Logger.ts Class Unit Tests", () => { const logger = new Logger(loggerOptions); logger.verbose("Message", testCorrelationId); - expect(logStore[LogLevel.Verbose].includes(testCorrelationId)).toBe( - true - ); + expect(logStore[LogLevel.Verbose]).toContain(testCorrelationId); }); it("CorrelationId passed in log message takes precedence over correlationId in Logger configurations", () => { @@ -399,12 +464,10 @@ describe("Logger.ts Class Unit Tests", () => { }); logger.verbose("Message", testCorrelationId); - expect(logStore[LogLevel.Verbose].includes(testCorrelationId)).toBe( - true + expect(logStore[LogLevel.Verbose]).toContain(testCorrelationId); + expect(logStore[LogLevel.Verbose]).not.toContain( + optionsCorrelationId ); - expect( - logStore[LogLevel.Verbose].includes(optionsCorrelationId) - ).toBe(false); }); it("CorrelationId on Logger will be used if an empty string is passed in the log message", () => { @@ -412,9 +475,7 @@ describe("Logger.ts Class Unit Tests", () => { const logger = new Logger(loggerOptions, testCorrelationId); logger.verbose("Message", ""); - expect(logStore[LogLevel.Verbose].includes(testCorrelationId)).toBe( - true - ); + expect(logStore[LogLevel.Verbose]).toContain(testCorrelationId); }); }); }); diff --git a/lib/msal-common/test/network/NetworkManager.spec.ts b/lib/msal-common/test/network/NetworkManager.spec.ts index 832daaa4d5..7ca18eb9cc 100644 --- a/lib/msal-common/test/network/NetworkManager.spec.ts +++ b/lib/msal-common/test/network/NetworkManager.spec.ts @@ -3,17 +3,16 @@ * Licensed under the MIT License. */ -import sinon from "sinon"; -import { ThrottlingUtils } from "../../src/network/ThrottlingUtils"; -import { RequestThumbprint } from "../../src/network/RequestThumbprint"; +import { ThrottlingUtils } from "../../src/network/ThrottlingUtils.js"; +import { RequestThumbprint } from "../../src/network/RequestThumbprint.js"; import { NetworkManager, NetworkResponse, -} from "../../src/network/NetworkManager"; -import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse"; -import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils"; -import { NetworkRequestOptions } from "../../src/network/INetworkModule"; -import { ServerError } from "../../src/error/ServerError"; +} from "../../src/network/NetworkManager.js"; +import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse.js"; +import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils.js"; +import { NetworkRequestOptions } from "../../src/network/INetworkModule.js"; +import { ServerError } from "../../src/error/ServerError.js"; import { AUTHENTICATION_RESULT, NETWORK_REQUEST_OPTIONS, @@ -21,17 +20,17 @@ import { THROTTLING_ENTITY, DEFAULT_NETWORK_IMPLEMENTATION, TEST_CONFIG, -} from "../test_kit/StringConstants"; +} from "../test_kit/StringConstants.js"; import { ClientAuthError, ClientAuthErrorCodes, -} from "../../src/error/ClientAuthError"; -import { Logger } from "../../src/logger/Logger"; +} from "../../src/error/ClientAuthError.js"; +import { Logger } from "../../src/logger/Logger.js"; describe("NetworkManager", () => { describe("sendPostRequest", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("returns a response", async () => { @@ -49,13 +48,19 @@ describe("NetworkManager", () => { body: AUTHENTICATION_RESULT.body, status: 200, }; - const networkStub = sinon - .stub(networkInterface, "sendPostRequestAsync") - .returns(Promise.resolve(mockRes)); - const getThrottlingStub = sinon.stub(cache, "getThrottlingCache"); - const setThrottlingStub = sinon.stub(cache, "setThrottlingCache"); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon.stub(Date, "now").callsFake(() => 1); + const networkStub = jest + .spyOn(networkInterface, "sendPostRequestAsync") + .mockResolvedValue(mockRes); + const getThrottlingStub = jest + .spyOn(cache, "getThrottlingCache") + .mockImplementation(); + const setThrottlingStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(Date, "now").mockReturnValue(1); const res = await networkManager.sendPostRequest( @@ -64,10 +69,10 @@ describe("NetworkManager", () => { options ); - sinon.assert.callCount(networkStub, 1); - sinon.assert.callCount(getThrottlingStub, 1); - sinon.assert.callCount(setThrottlingStub, 0); - sinon.assert.callCount(removeItemStub, 0); + expect(networkStub).toHaveBeenCalledTimes(1); + expect(getThrottlingStub).toHaveBeenCalledTimes(1); + expect(setThrottlingStub).toHaveBeenCalledTimes(0); + expect(removeItemStub).toHaveBeenCalledTimes(0); expect(res).toEqual(mockRes); }); @@ -82,16 +87,19 @@ describe("NetworkManager", () => { const thumbprint: RequestThumbprint = THUMBPRINT; const options: NetworkRequestOptions = NETWORK_REQUEST_OPTIONS; const mockThrottlingEntity = THROTTLING_ENTITY; - const networkStub = sinon.stub( - networkInterface, - "sendPostRequestAsync" - ); - const getThrottlingStub = sinon - .stub(cache, "getThrottlingCache") - .returns(mockThrottlingEntity); - const setThrottlingStub = sinon.stub(cache, "setThrottlingCache"); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon.stub(Date, "now").callsFake(() => 1); + const networkStub = jest + .spyOn(networkInterface, "sendPostRequestAsync") + .mockImplementation(); + const getThrottlingStub = jest + .spyOn(cache, "getThrottlingCache") + .mockReturnValue(mockThrottlingEntity); + const setThrottlingStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(Date, "now").mockReturnValue(1); try { await networkManager.sendPostRequest( @@ -101,10 +109,10 @@ describe("NetworkManager", () => { ); } catch {} - sinon.assert.callCount(networkStub, 0); - sinon.assert.callCount(getThrottlingStub, 1); - sinon.assert.callCount(setThrottlingStub, 0); - sinon.assert.callCount(removeItemStub, 0); + expect(networkStub).toHaveBeenCalledTimes(0); + expect(getThrottlingStub).toHaveBeenCalledTimes(1); + expect(setThrottlingStub).toHaveBeenCalledTimes(0); + expect(removeItemStub).toHaveBeenCalledTimes(0); expect(() => ThrottlingUtils.preProcess(cache, thumbprint) ).toThrowError(ServerError); @@ -126,15 +134,19 @@ describe("NetworkManager", () => { status: 200, }; const mockThrottlingEntity = THROTTLING_ENTITY; - const networkStub = sinon - .stub(networkInterface, "sendPostRequestAsync") - .returns(Promise.resolve(mockRes)); - const getThrottlingStub = sinon - .stub(cache, "getThrottlingCache") - .returns(mockThrottlingEntity); - const setThrottlingStub = sinon.stub(cache, "setThrottlingCache"); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon.stub(Date, "now").callsFake(() => 10); + const networkStub = jest + .spyOn(networkInterface, "sendPostRequestAsync") + .mockResolvedValue(mockRes); + const getThrottlingStub = jest + .spyOn(cache, "getThrottlingCache") + .mockReturnValue(mockThrottlingEntity); + const setThrottlingStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(Date, "now").mockReturnValue(10); const res = await networkManager.sendPostRequest( @@ -143,10 +155,10 @@ describe("NetworkManager", () => { options ); - sinon.assert.callCount(networkStub, 1); - sinon.assert.callCount(getThrottlingStub, 1); - sinon.assert.callCount(setThrottlingStub, 0); - sinon.assert.callCount(removeItemStub, 1); + expect(networkStub).toHaveBeenCalledTimes(1); + expect(getThrottlingStub).toHaveBeenCalledTimes(1); + expect(setThrottlingStub).toHaveBeenCalledTimes(0); + expect(removeItemStub).toHaveBeenCalledTimes(1); expect(res).toEqual(mockRes); }); @@ -165,13 +177,19 @@ describe("NetworkManager", () => { body: AUTHENTICATION_RESULT.body, status: 500, }; - const networkStub = sinon - .stub(networkInterface, "sendPostRequestAsync") - .returns(Promise.resolve(mockRes)); - const getThrottlingStub = sinon.stub(cache, "getThrottlingCache"); - const setThrottlingStub = sinon.stub(cache, "setThrottlingCache"); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon.stub(Date, "now").callsFake(() => 1); + const networkStub = jest + .spyOn(networkInterface, "sendPostRequestAsync") + .mockResolvedValue(mockRes); + const getThrottlingStub = jest + .spyOn(cache, "getThrottlingCache") + .mockImplementation(); + const setThrottlingStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(Date, "now").mockReturnValue(1); const res = await networkManager.sendPostRequest( @@ -180,10 +198,10 @@ describe("NetworkManager", () => { options ); - sinon.assert.callCount(networkStub, 1); - sinon.assert.callCount(getThrottlingStub, 1); - sinon.assert.callCount(setThrottlingStub, 1); - sinon.assert.callCount(removeItemStub, 0); + expect(networkStub).toHaveBeenCalledTimes(1); + expect(getThrottlingStub).toHaveBeenCalledTimes(1); + expect(setThrottlingStub).toHaveBeenCalledTimes(1); + expect(removeItemStub).toHaveBeenCalledTimes(0); expect(res).toEqual(mockRes); }); @@ -198,9 +216,10 @@ describe("NetworkManager", () => { const thumbprint: RequestThumbprint = THUMBPRINT; const options: NetworkRequestOptions = NETWORK_REQUEST_OPTIONS; - sinon - .stub(networkInterface, "sendPostRequestAsync") - .returns(Promise.reject("Fetch failed")); + jest.spyOn( + networkInterface, + "sendPostRequestAsync" + ).mockRejectedValue(new Error("Fetch failed")); networkManager .sendPostRequest( diff --git a/lib/msal-common/test/network/ThrottlingUtils.spec.ts b/lib/msal-common/test/network/ThrottlingUtils.spec.ts index 214f1fdca8..44e8131f9b 100644 --- a/lib/msal-common/test/network/ThrottlingUtils.spec.ts +++ b/lib/msal-common/test/network/ThrottlingUtils.spec.ts @@ -3,22 +3,25 @@ * Licensed under the MIT License. */ -import sinon from "sinon"; -import { ThrottlingUtils } from "../../src/network/ThrottlingUtils"; -import { RequestThumbprint } from "../../src/network/RequestThumbprint"; -import { ThrottlingEntity } from "../../src/cache/entities/ThrottlingEntity"; -import { NetworkResponse } from "../../src/network/NetworkManager"; -import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse"; -import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils"; +import { ThrottlingUtils } from "../../src/network/ThrottlingUtils.js"; +import { RequestThumbprint } from "../../src/network/RequestThumbprint.js"; +import { ThrottlingEntity } from "../../src/cache/entities/ThrottlingEntity.js"; +import { NetworkResponse } from "../../src/network/NetworkManager.js"; +import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse.js"; +import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils.js"; import { THUMBPRINT, THROTTLING_ENTITY, TEST_CONFIG, -} from "../test_kit/StringConstants"; -import { ServerError } from "../../src/error/ServerError"; -import { BaseAuthRequest, Logger } from "../../src"; +} from "../test_kit/StringConstants.js"; +import { ServerError } from "../../src/error/ServerError.js"; +import { BaseAuthRequest, Logger } from "../../src/index.js"; describe("ThrottlingUtils", () => { + afterAll(() => { + jest.restoreAllMocks(); + }); + describe("generateThrottlingStorageKey", () => { it("returns a throttling key", () => { const thumbprint: RequestThumbprint = THUMBPRINT; @@ -32,7 +35,7 @@ describe("ThrottlingUtils", () => { describe("preProcess", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("checks the cache and throws an error", () => { @@ -43,16 +46,18 @@ describe("ThrottlingUtils", () => { mockCrypto, new Logger({}) ); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon - .stub(cache, "getThrottlingCache") - .callsFake(() => thumbprintValue); - sinon.stub(Date, "now").callsFake(() => 1); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(cache, "getThrottlingCache").mockReturnValue( + thumbprintValue + ); + jest.spyOn(Date, "now").mockReturnValue(1); try { ThrottlingUtils.preProcess(cache, thumbprint); } catch {} - sinon.assert.callCount(removeItemStub, 0); + expect(removeItemStub).toHaveBeenCalledTimes(0); expect(() => ThrottlingUtils.preProcess(cache, thumbprint) @@ -67,14 +72,16 @@ describe("ThrottlingUtils", () => { mockCrypto, new Logger({}) ); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon - .stub(cache, "getThrottlingCache") - .callsFake(() => thumbprintValue); - sinon.stub(Date, "now").callsFake(() => 10); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(cache, "getThrottlingCache").mockReturnValue( + thumbprintValue + ); + jest.spyOn(Date, "now").mockReturnValue(10); ThrottlingUtils.preProcess(cache, thumbprint); - sinon.assert.callCount(removeItemStub, 1); + expect(removeItemStub).toHaveBeenCalledTimes(1); expect(() => ThrottlingUtils.preProcess(cache, thumbprint) @@ -88,11 +95,13 @@ describe("ThrottlingUtils", () => { mockCrypto, new Logger({}) ); - const removeItemStub = sinon.stub(cache, "removeItem"); - sinon.stub(cache, "getThrottlingCache").callsFake(() => null); + const removeItemStub = jest + .spyOn(cache, "removeItem") + .mockImplementation(); + jest.spyOn(cache, "getThrottlingCache").mockReturnValue(null); ThrottlingUtils.preProcess(cache, thumbprint); - sinon.assert.callCount(removeItemStub, 0); + expect(removeItemStub).toHaveBeenCalledTimes(0); expect(() => ThrottlingUtils.preProcess(cache, thumbprint) @@ -102,7 +111,7 @@ describe("ThrottlingUtils", () => { describe("postProcess", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("sets an item in the cache", () => { @@ -117,10 +126,12 @@ describe("ThrottlingUtils", () => { mockCrypto, new Logger({}) ); - const setItemStub = sinon.stub(cache, "setThrottlingCache"); + const setItemStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); ThrottlingUtils.postProcess(cache, thumbprint, res); - sinon.assert.callCount(setItemStub, 1); + expect(setItemStub).toHaveBeenCalledTimes(1); }); it("does not set an item in the cache", () => { @@ -135,10 +146,12 @@ describe("ThrottlingUtils", () => { mockCrypto, new Logger({}) ); - const setItemStub = sinon.stub(cache, "setThrottlingCache"); + const setItemStub = jest + .spyOn(cache, "setThrottlingCache") + .mockImplementation(); ThrottlingUtils.postProcess(cache, thumbprint, res); - sinon.assert.callCount(setItemStub, 0); + expect(setItemStub).toHaveBeenCalledTimes(0); }); }); @@ -231,11 +244,7 @@ describe("ThrottlingUtils", () => { describe("calculateThrottleTime", () => { beforeAll(() => { - sinon.stub(Date, "now").callsFake(() => 5000); - }); - - afterAll(() => { - sinon.restore(); + jest.spyOn(Date, "now").mockReturnValue(5000); }); it("returns calculated time to throttle", () => { @@ -264,10 +273,6 @@ describe("ThrottlingUtils", () => { }); describe("removeThrottle", () => { - afterEach(() => { - sinon.restore(); - }); - it("removes the entry from storage", () => { const cache = new MockStorageClass( TEST_CONFIG.MSAL_CLIENT_ID, diff --git a/lib/msal-common/test/request/RequestParameterBuilder.spec.ts b/lib/msal-common/test/request/RequestParameterBuilder.spec.ts index c37bd15482..cb900b7bee 100644 --- a/lib/msal-common/test/request/RequestParameterBuilder.spec.ts +++ b/lib/msal-common/test/request/RequestParameterBuilder.spec.ts @@ -5,8 +5,8 @@ import { GrantType, AuthenticationScheme, HeaderNames, -} from "../../src/utils/Constants"; -import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys"; +} from "../../src/utils/Constants.js"; +import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys.js"; import { TEST_CONFIG, TEST_URIS, @@ -15,19 +15,22 @@ import { TEST_POP_VALUES, TEST_DATA_CLIENT_INFO, TEST_SSH_VALUES, -} from "../test_kit/StringConstants"; -import { RequestParameterBuilder } from "../../src/request/RequestParameterBuilder"; -import sinon from "sinon"; +} from "../test_kit/StringConstants.js"; +import { RequestParameterBuilder } from "../../src/request/RequestParameterBuilder.js"; import { ClientConfigurationErrorCodes, ClientConfigurationErrorMessage, createClientConfigurationError, -} from "../../src/error/ClientConfigurationError"; -import { ClientAssertion, ClientAssertionCallback } from "../../src"; -import { getClientAssertion } from "../../src/utils/ClientAssertionUtils"; -import { ClientAssertionConfig } from "../../src/account/ClientCredentials"; +} from "../../src/error/ClientConfigurationError.js"; +import { ClientAssertion, ClientAssertionCallback } from "../../src/index.js"; +import { getClientAssertion } from "../../src/utils/ClientAssertionUtils.js"; +import { ClientAssertionConfig } from "../../src/account/ClientCredentials.js"; describe("RequestParameterBuilder unit tests", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + it("constructor", () => { const requestParameterBuilder = new RequestParameterBuilder(); expect(requestParameterBuilder).toBeInstanceOf(RequestParameterBuilder); @@ -367,19 +370,14 @@ describe("RequestParameterBuilder unit tests", () => { it("throws error if claims is not stringified JSON object", () => { const claims = "not-a-valid-JSON-object"; - sinon - .stub( - RequestParameterBuilder.prototype, - "addClientCapabilitiesToClaims" - ) - .returns(claims); + jest.spyOn( + RequestParameterBuilder.prototype, + "addClientCapabilitiesToClaims" + ).mockReturnValue(claims); const requestParameterBuilder = new RequestParameterBuilder(); - expect(() => - requestParameterBuilder.addClaims(claims, []) - ).toThrowError( + expect(() => requestParameterBuilder.addClaims(claims, [])).toThrow( ClientConfigurationErrorMessage.invalidClaimsRequest.desc ); - sinon.restore(); }); it("adds clientAssertion (string) and assertionType if they are provided by the developer", async () => { @@ -416,7 +414,7 @@ describe("RequestParameterBuilder unit tests", () => { ).toBe(true); }); - it("doesn't add client assertion (string) and client assertion type if they are empty strings", async () => { + it("does not add client assertion (string) and client assertion type if they are empty strings", async () => { const clientAssertion: ClientAssertion = { assertion: "", assertionType: "", @@ -484,7 +482,7 @@ describe("RequestParameterBuilder unit tests", () => { ).toBe(true); }); - it("doesn't add client assertion (ClientAssertionCallback) and client assertion type if they are empty strings", async () => { + it("does not add client assertion (ClientAssertionCallback) and client assertion type if they are empty strings", async () => { const ClientAssertionCallback: ClientAssertionCallback = ( _config: ClientAssertionConfig ) => { diff --git a/lib/msal-common/test/request/ScopeSet.spec.ts b/lib/msal-common/test/request/ScopeSet.spec.ts index 8860800d37..f115baea9e 100644 --- a/lib/msal-common/test/request/ScopeSet.spec.ts +++ b/lib/msal-common/test/request/ScopeSet.spec.ts @@ -1,20 +1,23 @@ -import { ScopeSet } from "../../src/request/ScopeSet"; -import sinon from "sinon"; +import { ScopeSet } from "../../src/request/ScopeSet.js"; import { OIDC_DEFAULT_SCOPES, OIDC_SCOPES, Constants, -} from "../../src/utils/Constants"; +} from "../../src/utils/Constants.js"; import { ClientConfigurationErrorMessage, ClientConfigurationError, -} from "../../src/error/ClientConfigurationError"; +} from "../../src/error/ClientConfigurationError.js"; import { ClientAuthErrorMessage, ClientAuthError, -} from "../../src/error/ClientAuthError"; +} from "../../src/error/ClientAuthError.js"; describe("ScopeSet.ts", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + describe("Constructor and scope validation", () => { it("Throws error if scopes are null or empty and required", () => { // @ts-ignore @@ -142,10 +145,6 @@ describe("ScopeSet.ts", () => { scopes = new ScopeSet([testScope]); }); - afterEach(() => { - sinon.restore(); - }); - it("containsScope() checks if a given scope is present in the set of scopes", () => { expect(scopes.containsScope(Constants.OPENID_SCOPE)).toBe(false); expect(scopes.containsScope("notinset")).toBe(false); @@ -198,19 +197,19 @@ describe("ScopeSet.ts", () => { it("appendScope() does nothing if given scope is empty, null or undefined", () => { const testScopes = [testScope]; - const setAddSpy = sinon.spy(Set.prototype, "add"); + const setAddSpy = jest.spyOn(Set.prototype, "add"); scopes.appendScope(""); - expect(setAddSpy.called).toBe(false); + expect(setAddSpy).not.toHaveBeenCalled(); expect(scopes.asArray()).toEqual(testScopes); // @ts-ignore scopes.appendScope(null); - expect(setAddSpy.called).toBe(false); + expect(setAddSpy).not.toHaveBeenCalled(); expect(scopes.asArray()).toEqual(testScopes); // @ts-ignore scopes.appendScope(undefined); - expect(setAddSpy.called).toBe(false); + expect(setAddSpy).not.toHaveBeenCalled(); expect(scopes.asArray()).toEqual(testScopes); }); @@ -437,10 +436,6 @@ describe("ScopeSet.ts", () => { lowercaseScopeSet = new ScopeSet([testScope]); }); - afterEach(() => { - sinon.restore(); - }); - it("asArray() returns ScopeSet as an array", () => { const scopeArr = nonRequiredScopeSet.asArray(); expect(Array.isArray(scopeArr)).toBe(true); diff --git a/lib/msal-common/test/telemetry/ServerTelemetryManager.spec.ts b/lib/msal-common/test/telemetry/ServerTelemetryManager.spec.ts index ff4385369c..78b5084a36 100644 --- a/lib/msal-common/test/telemetry/ServerTelemetryManager.spec.ts +++ b/lib/msal-common/test/telemetry/ServerTelemetryManager.spec.ts @@ -3,15 +3,14 @@ * Licensed under the MIT License. */ -import { TEST_CONFIG } from "../test_kit/StringConstants"; -import sinon from "sinon"; -import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils"; -import { ServerTelemetryRequest } from "../../src/telemetry/server/ServerTelemetryRequest"; -import { ServerTelemetryManager } from "../../src/telemetry/server/ServerTelemetryManager"; -import { AuthError } from "../../src/error/AuthError"; -import { ServerTelemetryEntity } from "../../src/cache/entities/ServerTelemetryEntity"; -import { CacheOutcome } from "../../src/utils/Constants"; -import { Logger } from "../../src/logger/Logger"; +import { TEST_CONFIG } from "../test_kit/StringConstants.js"; +import { MockStorageClass, mockCrypto } from "../client/ClientTestUtils.js"; +import { ServerTelemetryRequest } from "../../src/telemetry/server/ServerTelemetryRequest.js"; +import { ServerTelemetryManager } from "../../src/telemetry/server/ServerTelemetryManager.js"; +import { AuthError } from "../../src/error/AuthError.js"; +import { ServerTelemetryEntity } from "../../src/cache/entities/ServerTelemetryEntity.js"; +import { CacheOutcome } from "../../src/utils/Constants.js"; +import { Logger } from "../../src/logger/Logger.js"; const testCacheManager = new MockStorageClass( TEST_CONFIG.MSAL_CLIENT_ID, @@ -32,7 +31,7 @@ const testTelemetryPayload: ServerTelemetryRequest = { describe("ServerTelemetryManager.ts", () => { afterEach(() => { testCacheManager.store = {}; - sinon.restore(); + jest.restoreAllMocks(); }); describe("cacheFailedRequest", () => { @@ -227,7 +226,10 @@ describe("ServerTelemetryManager.ts", () => { }); it("Adds partial telemetry data if max size is reached and sets overflow flag to 1", () => { - sinon.stub(ServerTelemetryManager, "maxErrorsToSend").returns(1); + jest.spyOn( + ServerTelemetryManager, + "maxErrorsToSend" + ).mockReturnValue(1); const testCacheHits = 3; const failures = { failedRequests: [ @@ -278,7 +280,10 @@ describe("ServerTelemetryManager.ts", () => { describe("clear telemetry cache tests", () => { it("Removes telemetry cache entry if all errors were sent to server", () => { - sinon.stub(ServerTelemetryManager, "maxErrorsToSend").returns(1); + jest.spyOn( + ServerTelemetryManager, + "maxErrorsToSend" + ).mockReturnValue(1); const failures = { failedRequests: [testApiCode, testCorrelationId], errors: [testError], @@ -300,7 +305,10 @@ describe("ServerTelemetryManager.ts", () => { }); it("Removes partial telemetry data from cache if partial data was sent to server", () => { - sinon.stub(ServerTelemetryManager, "maxErrorsToSend").returns(1); + jest.spyOn( + ServerTelemetryManager, + "maxErrorsToSend" + ).mockReturnValue(1); const failures = { failedRequests: [ testApiCode, @@ -371,7 +379,7 @@ describe("ServerTelemetryManager.ts", () => { ).toBeLessThan(failures.errors.length); }); - it("maxErrorsToSend doesn't break on null and undefined values", () => { + it("maxErrorsToSend does not break on null and undefined values", () => { const failures = { failedRequests: [null, undefined, undefined, null], errors: [null, undefined], diff --git a/lib/msal-common/test/url/UrlString.spec.ts b/lib/msal-common/test/url/UrlString.spec.ts index 7a840f2b6d..f1a3762417 100644 --- a/lib/msal-common/test/url/UrlString.spec.ts +++ b/lib/msal-common/test/url/UrlString.spec.ts @@ -1,16 +1,15 @@ -import { TEST_URIS, TEST_HASHES } from "../test_kit/StringConstants"; -import { UrlString } from "../../src/url/UrlString"; +import { TEST_URIS, TEST_HASHES } from "../test_kit/StringConstants.js"; +import { UrlString } from "../../src/url/UrlString.js"; import { ClientConfigurationError, ClientConfigurationErrorCodes, createClientConfigurationError, -} from "../../src/error/ClientConfigurationError"; -import { IUri } from "../../src/url/IUri"; -import sinon from "sinon"; +} from "../../src/error/ClientConfigurationError.js"; +import { IUri } from "../../src/url/IUri.js"; describe("UrlString.ts Class Unit Tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("Creates a valid UrlString object", () => { @@ -40,9 +39,11 @@ describe("UrlString.ts Class Unit Tests", () => { it("validateAsUri throws error if uri components could not be extracted", () => { const urlComponentError = "Error getting url components"; - sinon - .stub(UrlString.prototype, "getUrlComponents") - .throws(urlComponentError); + jest.spyOn(UrlString.prototype, "getUrlComponents").mockImplementation( + () => { + throw urlComponentError; + } + ); let urlObj = new UrlString(TEST_URIS.TEST_REDIR_URI); expect(() => urlObj.validateAsUri()).toThrowError( createClientConfigurationError( @@ -235,7 +236,7 @@ describe("UrlString.ts Class Unit Tests", () => { }); describe("getAbsoluteUrl tests", () => { - it("Returns url provided if it's already absolute", () => { + it("Returns url provided if it is already absolute", () => { const absoluteUrl = "https://localhost:30662"; expect( UrlString.getAbsoluteUrl(absoluteUrl, absoluteUrl + "/testPath") diff --git a/lib/msal-common/test/utils/ProtocolUtils.spec.ts b/lib/msal-common/test/utils/ProtocolUtils.spec.ts index 89b651a506..ff6c8c8ca3 100644 --- a/lib/msal-common/test/utils/ProtocolUtils.spec.ts +++ b/lib/msal-common/test/utils/ProtocolUtils.spec.ts @@ -1,16 +1,15 @@ -import { ProtocolUtils } from "../../src/utils/ProtocolUtils"; +import { ProtocolUtils } from "../../src/utils/ProtocolUtils.js"; import { RANDOM_TEST_GUID, TEST_CRYPTO_VALUES, TEST_POP_VALUES, -} from "../test_kit/StringConstants"; -import { ICrypto } from "../../src/crypto/ICrypto"; -import { Constants } from "../../src/utils/Constants"; -import sinon from "sinon"; +} from "../test_kit/StringConstants.js"; +import { ICrypto } from "../../src/crypto/ICrypto.js"; +import { Constants } from "../../src/utils/Constants.js"; import { ClientAuthError, ClientAuthErrorMessage, -} from "../../src/error/ClientAuthError"; +} from "../../src/error/ClientAuthError.js"; describe("ProtocolUtils.ts Class Unit Tests", () => { const userState = "userState"; @@ -79,7 +78,7 @@ describe("ProtocolUtils.ts Class Unit Tests", () => { }); afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); it("setRequestState() appends library state to given state", () => { diff --git a/package-lock.json b/package-lock.json index 2b1e68412e..2916264020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -396,7 +396,6 @@ "@types/jest": "^29.5.0", "@types/lodash": "^4.14.182", "@types/node": "^20.3.1", - "@types/sinon": "^7.5.0", "eslint-config-msal": "file:../../shared-configs/eslint-config-msal", "jest": "^29.5.0", "lodash": "^4.17.21", @@ -406,7 +405,6 @@ "rollup": "^3.29.5", "rollup-msal": "file:../../shared-configs/rollup-msal", "shx": "^0.3.2", - "sinon": "^7.5.0", "ts-jest": "^29.1.0", "ts-jest-resolver": "^2.0.1", "ts-node": "^10.9.1", From 0b87961edf15f9d197becdf037277c689cb82f89 Mon Sep 17 00:00:00 2001 From: Robbie Ginsburg Date: Wed, 25 Sep 2024 14:10:57 -0400 Subject: [PATCH 2/4] second batch of sinon to jest --- .../client/AuthorizationCodeClient.spec.ts | 1724 ++++++++--------- .../test/client/RefreshTokenClient.spec.ts | 563 +++--- .../test/client/SilentFlowClient.spec.ts | 733 +++---- .../test/response/ResponseHandler.spec.ts | 307 ++- 4 files changed, 1580 insertions(+), 1747 deletions(-) diff --git a/lib/msal-common/test/client/AuthorizationCodeClient.spec.ts b/lib/msal-common/test/client/AuthorizationCodeClient.spec.ts index a0c19b664e..228a6837fb 100644 --- a/lib/msal-common/test/client/AuthorizationCodeClient.spec.ts +++ b/lib/msal-common/test/client/AuthorizationCodeClient.spec.ts @@ -1,4 +1,3 @@ -import sinon from "sinon"; import { ALTERNATE_OPENID_CONFIG_RESPONSE, AUTHENTICATION_RESULT, @@ -16,9 +15,9 @@ import { TEST_SSH_VALUES, AUTHENTICATION_RESULT_WITH_HEADERS, CORS_RESPONSE_HEADERS, -} from "../test_kit/StringConstants"; -import { ClientConfiguration } from "../../src/config/ClientConfiguration"; -import { BaseClient } from "../../src/client/BaseClient"; +} from "../test_kit/StringConstants.js"; +import { ClientConfiguration } from "../../src/config/ClientConfiguration.js"; +import { BaseClient } from "../../src/client/BaseClient.js"; import { PromptValue, ResponseMode, @@ -27,42 +26,40 @@ import { Constants, HeaderNames, ONE_DAY_IN_MS, -} from "../../src/utils/Constants"; -import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys"; -import { ClientTestUtils, MockStorageClass } from "./ClientTestUtils"; -import { TestError } from "../test_kit/TestErrors"; -import { Authority } from "../../src/authority/Authority"; -import { AuthorizationCodeClient } from "../../src/client/AuthorizationCodeClient"; -import { CommonAuthorizationUrlRequest } from "../../src/request/CommonAuthorizationUrlRequest"; -import { TokenClaims } from "../../src/account/TokenClaims"; -import { ServerError } from "../../src/error/ServerError"; -import { CommonAuthorizationCodeRequest } from "../../src/request/CommonAuthorizationCodeRequest"; -import * as AuthToken from "../../src/account/AuthToken"; +} from "../../src/utils/Constants.js"; +import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys.js"; +import { ClientTestUtils, MockStorageClass } from "./ClientTestUtils.js"; +import { TestError } from "../test_kit/TestErrors.js"; +import { Authority } from "../../src/authority/Authority.js"; +import { AuthorizationCodeClient } from "../../src/client/AuthorizationCodeClient.js"; +import { CommonAuthorizationUrlRequest } from "../../src/request/CommonAuthorizationUrlRequest.js"; +import { TokenClaims } from "../../src/account/TokenClaims.js"; +import { ServerError } from "../../src/error/ServerError.js"; +import { CommonAuthorizationCodeRequest } from "../../src/request/CommonAuthorizationCodeRequest.js"; +import * as AuthToken from "../../src/account/AuthToken.js"; import { ClientAuthErrorCodes, createClientAuthError, -} from "../../src/error/ClientAuthError"; +} from "../../src/error/ClientAuthError.js"; import { AuthError, CcsCredentialType, ClientConfigurationErrorCodes, createClientConfigurationError, -} from "../../src"; -import { ProtocolMode } from "../../src/authority/ProtocolMode"; +} from "../../src/index.js"; +import { ProtocolMode } from "../../src/authority/ProtocolMode.js"; describe("AuthorizationCodeClient unit tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); describe("Constructor", () => { it("creates a AuthorizationCodeClient that extends BaseClient", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client = new AuthorizationCodeClient(config); @@ -74,12 +71,10 @@ describe("AuthorizationCodeClient unit tests", () => { describe("Authorization url creation", () => { it("Creates an authorization url with default parameters", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client = new AuthorizationCodeClient(config); @@ -163,12 +158,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Creates an authorization url passing in optional parameters", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -300,12 +293,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Adds CCS entry if loginHint is provided", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -343,12 +334,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Adds CCS entry if account is provided", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -412,12 +401,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("prefers login_hint claim over sid/upn if both provided", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -488,12 +475,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("skips login_hint claim if domainHint param is set", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -571,12 +556,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("picks up both loginHint and domainHint params", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -649,12 +632,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Prefers sid over loginHint if both provided and prompt=None", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -691,12 +672,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Prefers loginHint over sid if both provided and prompt!=None", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -729,12 +708,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Ignores sid if prompt!=None", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -762,12 +739,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Prefers loginHint over Account if both provided and account does not have token claims", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -806,12 +781,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Uses sid from account if not provided in request and prompt=None, overrides login_hint", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -872,12 +845,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Uses loginHint instead of sid from account prompt!=None", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -953,12 +924,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Uses login_hint instead of username if sid is not present in token claims for account or request", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1033,12 +1002,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Sets login_hint to Account.username if login_hint and sid are not provided", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1069,12 +1036,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Ignores Account if prompt is select_account", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1102,12 +1067,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Ignores loginHint if prompt is select_account", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1135,12 +1098,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Ignores sid if prompt is select_account", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1168,12 +1129,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Creates a login URL with scopes from given token request", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(ALTERNATE_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(ALTERNATE_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1204,22 +1163,19 @@ describe("AuthorizationCodeClient unit tests", () => { it("Does not append an extra '?' when the authorization endpoint already contains a query string", async () => { // Override with alternate authority openid_config - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromHardcodedValues" - ) - .returns({ - token_endpoint: - "https://login.windows.net/common/oauth2/v2.0/token?param1=value1", - issuer: "https://login.windows.net/{tenantid}/v2.0", - userinfo_endpoint: - "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.windows.net/common/oauth2/v2.0/authorize?param1=value1", - end_session_endpoint: - "https://login.windows.net/common/oauth2/v2.0/logout?param1=value1", - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromHardcodedValues" + ).mockReturnValue({ + token_endpoint: + "https://login.windows.net/common/oauth2/v2.0/token?param1=value1", + issuer: "https://login.windows.net/{tenantid}/v2.0", + userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", + authorization_endpoint: + "https://login.windows.net/common/oauth2/v2.0/authorize?param1=value1", + end_session_endpoint: + "https://login.windows.net/common/oauth2/v2.0/logout?param1=value1", + }); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1296,9 +1252,10 @@ describe("AuthorizationCodeClient unit tests", () => { it("Adds req-cnf as needed", async () => { // Override with alternate authority openid_config - sinon - .stub(Authority.prototype, "getEndpointMetadataFromNetwork") - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); @@ -1368,12 +1325,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("throws server error when error is in hash", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client: AuthorizationCodeClient = new AuthorizationCodeClient( @@ -1410,12 +1365,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Throws error if null code request is passed", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const client = new AuthorizationCodeClient(config); @@ -1435,12 +1388,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Throws error if code response does not contain authorization code", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); if (!config.storageInterface) { throw TestError.createTestSetupError( @@ -1474,19 +1425,17 @@ describe("AuthorizationCodeClient unit tests", () => { it("preventCorsPreflight=true does not add headers other than simpleRequest headers", async () => { // For more information about this test see: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - let stubCalled = false; - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + const executePostToTokenEndpointSpy: jest.SpyInstance = jest + .spyOn( AuthorizationCodeClient.prototype, "executePostToTokenEndpoint" ) - .callsFake( + .mockImplementation( + // @ts-expect-error ( tokenEndpoint: string, queryString: string, @@ -1499,7 +1448,6 @@ describe("AuthorizationCodeClient unit tests", () => { ); }); - stubCalled = true; return Promise.resolve(AUTHENTICATION_RESULT); } ); @@ -1515,37 +1463,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -1559,7 +1509,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -1585,28 +1537,26 @@ describe("AuthorizationCodeClient unit tests", () => { state: testState, }); - expect(stubCalled).toBe(true); + expect(executePostToTokenEndpointSpy).toHaveBeenCalled(); }); it("preventCorsPreflight=false adds headers to request", async () => { // For more information about this test see: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - let stubCalled = false; - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const reqHeaders = [ ...CORS_SIMPLE_REQUEST_HEADERS, HeaderNames.CCS_HEADER.toLowerCase(), ]; - sinon - .stub( + const executePostToTokenEndpointSpy: jest.SpyInstance = jest + .spyOn( AuthorizationCodeClient.prototype, "executePostToTokenEndpoint" ) - .callsFake( + .mockImplementation( + // @ts-expect-error ( tokenEndpoint: string, queryString: string, @@ -1619,7 +1569,6 @@ describe("AuthorizationCodeClient unit tests", () => { ); }); - stubCalled = true; return Promise.resolve(AUTHENTICATION_RESULT); } ); @@ -1635,37 +1584,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -1679,7 +1630,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -1705,24 +1658,22 @@ describe("AuthorizationCodeClient unit tests", () => { state: testState, }); - expect(stubCalled).toBe(true); + expect(executePostToTokenEndpointSpy).toHaveBeenCalled(); }); it("Does not add headers that do not qualify for a simple request", async () => { // For more information about this test see: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - let stubCalled = false; - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + const executePostToTokenEndpointSpy: jest.SpyInstance = jest + .spyOn( AuthorizationCodeClient.prototype, "executePostToTokenEndpoint" ) - .callsFake( + .mockImplementation( + // @ts-expect-error ( tokenEndpoint: string, queryString: string, @@ -1735,7 +1686,6 @@ describe("AuthorizationCodeClient unit tests", () => { ); }); - stubCalled = true; return Promise.resolve(AUTHENTICATION_RESULT); } ); @@ -1750,37 +1700,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -1794,7 +1746,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -1816,22 +1770,18 @@ describe("AuthorizationCodeClient unit tests", () => { state: testState, }); - expect(stubCalled).toBe(true); + expect(executePostToTokenEndpointSpy).toHaveBeenCalled(); }); it("Throws error if max age is equal to 0 or has transpired since the last end-user authentication", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -1843,37 +1793,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -1888,7 +1840,9 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: "123523", auth_time: Date.now() - ONE_DAY_IN_MS * 2, }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -1917,18 +1871,14 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Throws error if max age is requested and auth time is not included in the token claims", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -1940,37 +1890,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -1985,7 +1937,9 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: "123523", // "auth_time" is missing for the purpose of this test }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -2014,23 +1968,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Acquires a token successfully", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); - if (!config.cryptoInterface) { throw TestError.createTestSetupError( "configuration cryptoInterface not initialized correctly." @@ -2041,37 +1990,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -2085,7 +2036,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -2123,12 +2076,12 @@ describe("AuthorizationCodeClient unit tests", () => { Date.now() + AUTHENTICATION_RESULT.body.expires_in * 1000 >= authenticationResult.expiresOn.getMilliseconds() ).toBe(true); - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes( `${AADServerParamKeys.SCOPE}=${TEST_CONFIG.DEFAULT_GRAPH_SCOPE}%20${Constants.OPENID_SCOPE}%20${Constants.PROFILE_SCOPE}%20${Constants.OFFLINE_ACCESS_SCOPE}` @@ -2194,23 +2147,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Acquires a token successfully when max age is provided and has not transpired yet", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); - if (!config.cryptoInterface) { throw TestError.createTestSetupError( "configuration cryptoInterface not initialized correctly." @@ -2221,37 +2169,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -2266,7 +2216,9 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: "123523", auth_time: Date.now() - ONE_DAY_IN_MS * 2, }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -2305,12 +2257,12 @@ describe("AuthorizationCodeClient unit tests", () => { Date.now() + AUTHENTICATION_RESULT.body.expires_in * 1000 >= authenticationResult.expiresOn.getMilliseconds() ).toBe(true); - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes( `${AADServerParamKeys.SCOPE}=${TEST_CONFIG.DEFAULT_GRAPH_SCOPE}%20${Constants.OPENID_SCOPE}%20${Constants.PROFILE_SCOPE}%20${Constants.OFFLINE_ACCESS_SCOPE}` @@ -2376,32 +2328,27 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Adds tokenQueryParameters to the /token request", (done) => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string) => { - try { - expect( - url.includes( - "/token?testParam1=testValue1&testParam3=testValue3" - ) - ).toBeTruthy(); - expect( - !url.includes("/token?testParam2=") - ).toBeTruthy(); - done(); - } catch (error) { - done(error); - } - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string) => { + try { + expect( + url.includes( + "/token?testParam1=testValue1&testParam3=testValue3" + ) + ).toBeTruthy(); + expect(!url.includes("/token?testParam2=")).toBeTruthy(); + done(); + } catch (error) { + done(error); + } + }); const client = new AuthorizationCodeClient(config); const authorizationCodeRequest: CommonAuthorizationCodeRequest = { @@ -2429,21 +2376,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Adds tokenBodyParameters to the /token request", (done) => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string, body: string) => { - expect(body).toContain("extra_body_parameter=true"); - done(); - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string, body: string) => { + expect(body).toContain("extra_body_parameter=true"); + done(); + }); if (!config.cryptoInterface || !config.systemOptions) { throw TestError.createTestSetupError( @@ -2475,21 +2419,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Adds return_spa_code=1 to body when enableSpaAuthCode is set", (done) => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string, body: string) => { - expect(body).toContain("return_spa_code=1"); - done(); - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string, body: string) => { + expect(body).toContain("return_spa_code=1"); + done(); + }); if (!config.cryptoInterface || !config.systemOptions) { throw TestError.createTestSetupError( @@ -2525,21 +2466,18 @@ describe("AuthorizationCodeClient unit tests", () => { this.includeRedirectUri = false; } } - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - TestAuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string, body: string) => { - expect(body).not.toContain("redirect_uri="); - done(); - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + TestAuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string, body: string) => { + expect(body).not.toContain("redirect_uri="); + done(); + }); if (!config.cryptoInterface || !config.systemOptions) { throw TestError.createTestSetupError( @@ -2571,23 +2509,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Sends the required parameters when a pop token is requested", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(POP_AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(POP_AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); - if (!config.cryptoInterface) { throw TestError.createTestSetupError( "configuration cryptoInterface not initialized correctly." @@ -2598,37 +2531,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); const signedJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJjbmYiOnsia2lkIjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyJ9fQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; @@ -2655,27 +2590,25 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon - .stub(AuthToken, "extractTokenClaims") - .callsFake( - ( - encodedToken: string, - base64Decode: (val: string) => string - ): TokenClaims => { - switch (encodedToken) { - case POP_AUTHENTICATION_RESULT.body.id_token: - return idTokenClaims as TokenClaims; - case POP_AUTHENTICATION_RESULT.body.access_token: - return { - cnf: { - kid: TEST_POP_VALUES.KID, - }, - }; - default: - return {}; - } + jest.spyOn(AuthToken, "extractTokenClaims").mockImplementation( + ( + encodedToken: string, + base64Decode: (val: string) => string + ): TokenClaims => { + switch (encodedToken) { + case POP_AUTHENTICATION_RESULT.body.id_token: + return idTokenClaims as TokenClaims; + case POP_AUTHENTICATION_RESULT.body.access_token: + return { + cnf: { + kid: TEST_POP_VALUES.KID, + }, + }; + default: + return {}; } - ); + } + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authenticationScheme: AuthenticationScheme.POP, @@ -2709,11 +2642,11 @@ describe("AuthorizationCodeClient unit tests", () => { // @ts-ignore authenticationResult.expiresOn.getMilliseconds() ).toBe(true); - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes( `${AADServerParamKeys.SCOPE}=${TEST_CONFIG.DEFAULT_GRAPH_SCOPE}%20${Constants.OPENID_SCOPE}%20${Constants.PROFILE_SCOPE}%20${Constants.OFFLINE_ACCESS_SCOPE}` @@ -2771,23 +2704,18 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Sends the required parameters when a SSH certificate is requested", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(POP_AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(POP_AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); - if (!config.cryptoInterface) { throw TestError.createTestSetupError( "configuration cryptoInterface not initialized correctly." @@ -2851,27 +2779,25 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon - .stub(AuthToken, "extractTokenClaims") - .callsFake( - ( - encodedToken: string, - base64Decode: (val: string) => string - ): TokenClaims => { - switch (encodedToken) { - case POP_AUTHENTICATION_RESULT.body.id_token: - return idTokenClaims as TokenClaims; - case POP_AUTHENTICATION_RESULT.body.access_token: - return { - cnf: { - kid: TEST_POP_VALUES.KID, - }, - }; - default: - return {}; - } + jest.spyOn(AuthToken, "extractTokenClaims").mockImplementation( + ( + encodedToken: string, + base64Decode: (val: string) => string + ): TokenClaims => { + switch (encodedToken) { + case POP_AUTHENTICATION_RESULT.body.id_token: + return idTokenClaims as TokenClaims; + case POP_AUTHENTICATION_RESULT.body.access_token: + return { + cnf: { + kid: TEST_POP_VALUES.KID, + }, + }; + default: + return {}; } - ); + } + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authenticationScheme: AuthenticationScheme.SSH, @@ -2904,11 +2830,11 @@ describe("AuthorizationCodeClient unit tests", () => { // @ts-ignore authenticationResult.expiresOn.getMilliseconds() ).toBe(true); - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes( `${AADServerParamKeys.SCOPE}=${TEST_CONFIG.DEFAULT_GRAPH_SCOPE}%20${Constants.OPENID_SCOPE}%20${Constants.PROFILE_SCOPE}%20${Constants.OFFLINE_ACCESS_SCOPE}` @@ -2966,18 +2892,14 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Throws missing SSH JWK error when the token request has Authentication Scheme set to SSH and SSH JWK is missing", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(POP_AUTHENTICATION_RESULT); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(POP_AUTHENTICATION_RESULT); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -3041,27 +2963,25 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon - .stub(AuthToken, "extractTokenClaims") - .callsFake( - ( - encodedToken: string, - base64Decode: (val: string) => string - ): TokenClaims => { - switch (encodedToken) { - case POP_AUTHENTICATION_RESULT.body.id_token: - return idTokenClaims as TokenClaims; - case POP_AUTHENTICATION_RESULT.body.access_token: - return { - cnf: { - kid: TEST_POP_VALUES.KID, - }, - }; - default: - return {}; - } + jest.spyOn(AuthToken, "extractTokenClaims").mockImplementation( + ( + encodedToken: string, + base64Decode: (val: string) => string + ): TokenClaims => { + switch (encodedToken) { + case POP_AUTHENTICATION_RESULT.body.id_token: + return idTokenClaims as TokenClaims; + case POP_AUTHENTICATION_RESULT.body.access_token: + return { + cnf: { + kid: TEST_POP_VALUES.KID, + }, + }; + default: + return {}; } - ); + } + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authenticationScheme: AuthenticationScheme.SSH, @@ -3091,26 +3011,22 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("properly handles expiration timestamps as strings", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves({ - ...AUTHENTICATION_RESULT, - body: { - ...AUTHENTICATION_RESULT.body, - expires_in: "3599", - ext_expires_in: "3599", - }, - }); - sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue({ + ...AUTHENTICATION_RESULT, + body: { + ...AUTHENTICATION_RESULT.body, + expires_in: "3599", + ext_expires_in: "3599", + }, + }); + jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); @@ -3124,37 +3040,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -3168,7 +3086,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3199,12 +3119,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Saves refresh_in correctly to the cache", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const authResult = { ...AUTHENTICATION_RESULT, body: { @@ -3212,17 +3130,14 @@ describe("AuthorizationCodeClient unit tests", () => { refresh_in: 1000, }, }; - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(authResult); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(authResult); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); - if (!config.cryptoInterface) { throw TestError.createTestSetupError( "configuration cryptoInterface not initialized correctly." @@ -3232,37 +3147,39 @@ describe("AuthorizationCodeClient unit tests", () => { const testState = `eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9${Constants.RESOURCE_DELIM}userState`; const decodedLibState = '{ "id": "testid", "ts": 1592846482 }'; - sinon - .stub(config.cryptoInterface, "base64Decode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.ENCODED_REQ_CNF: - return TEST_POP_VALUES.DECODED_REQ_CNF; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": - return decodedLibState; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Decode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.ENCODED_REQ_CNF: + return TEST_POP_VALUES.DECODED_REQ_CNF; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + case "eyAiaWQiOiAidGVzdGlkIiwgInRzIjogMTU5Mjg0NjQ4MiB9": + return decodedLibState; + default: + return input; + } + }); - sinon - .stub(config.cryptoInterface, "base64Encode") - .callsFake((input) => { - switch (input) { - case TEST_POP_VALUES.DECODED_REQ_CNF: - return TEST_POP_VALUES.ENCODED_REQ_CNF; - case "123-test-uid": - return "MTIzLXRlc3QtdWlk"; - case "456-test-utid": - return "NDU2LXRlc3QtdXRpZA=="; - case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: - return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - default: - return input; - } - }); + jest.spyOn( + config.cryptoInterface, + "base64Encode" + ).mockImplementation((input) => { + switch (input) { + case TEST_POP_VALUES.DECODED_REQ_CNF: + return TEST_POP_VALUES.ENCODED_REQ_CNF; + case "123-test-uid": + return "MTIzLXRlc3QtdWlk"; + case "456-test-utid": + return "NDU2LXRlc3QtdXRpZA=="; + case TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO: + return TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; + default: + return input; + } + }); // Set up stubs const idTokenClaims = { @@ -3276,7 +3193,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3317,9 +3236,9 @@ describe("AuthorizationCodeClient unit tests", () => { Date.now() + AUTHENTICATION_RESULT.body.expires_in * 1000 >= authenticationResult.expiresOn.getMilliseconds() ).toBe(true); - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); expect( accessTokenCacheItem && accessTokenCacheItem.refreshOn && @@ -3330,18 +3249,14 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("includes the requestId in the result when received in server response", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT_WITH_HEADERS); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT_WITH_HEADERS); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -3361,7 +3276,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3397,18 +3314,14 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("does not include the requestId in the result when none in server response", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - AuthorizationCodeClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + AuthorizationCodeClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -3427,7 +3340,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const client = new AuthorizationCodeClient(config); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3481,19 +3396,15 @@ describe("AuthorizationCodeClient unit tests", () => { config, performanceClient ); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - // @ts-ignore - client.networkManager, - "sendPostRequest" - ) - .resolves(AUTHENTICATION_RESULT_WITH_HEADERS); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + // @ts-ignore + client.networkManager, + "sendPostRequest" + ).mockResolvedValue(AUTHENTICATION_RESULT_WITH_HEADERS); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -3512,7 +3423,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3532,7 +3445,7 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: idTokenClaims.nonce, }); - expect(performanceClient.addFields).toBeCalledWith( + expect(performanceClient.addFields).toHaveBeenCalledWith( { httpVerToken: "xMsHttpVer", refreshTokenSize: @@ -3563,19 +3476,15 @@ describe("AuthorizationCodeClient unit tests", () => { config, performanceClient ); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub( - // @ts-ignore - client.networkManager, - "sendPostRequest" - ) - .resolves({ ...AUTHENTICATION_RESULT, headers: {} }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + // @ts-ignore + client.networkManager, + "sendPostRequest" + ).mockResolvedValue({ ...AUTHENTICATION_RESULT, headers: {} }); if (!config.cryptoInterface) { throw TestError.createTestSetupError( @@ -3594,7 +3503,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const authCodeRequest: CommonAuthorizationCodeRequest = { authority: Constants.DEFAULT_AUTHORITY, @@ -3630,13 +3541,11 @@ describe("AuthorizationCodeClient unit tests", () => { let config = await ClientTestUtils.createTestClientConfiguration( true ); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); @@ -3657,7 +3566,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const performanceClient = { startMeasurement: jest.fn(), endMeasurement: jest.fn(), @@ -3707,12 +3618,12 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: idTokenClaims.nonce, }); } catch {} - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes(`${AADServerParamKeys.X_CLIENT_CURR_TELEM}`) ).toBe(true); @@ -3725,13 +3636,11 @@ describe("AuthorizationCodeClient unit tests", () => { true, ProtocolMode.OIDC ); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + const createTokenRequestBodySpy = jest.spyOn( AuthorizationCodeClient.prototype, "createTokenRequestBody" ); @@ -3752,7 +3661,9 @@ describe("AuthorizationCodeClient unit tests", () => { tid: "3338040d-6c67-4c5b-b112-36a304b66dad", nonce: "123523", }; - sinon.stub(AuthToken, "extractTokenClaims").returns(idTokenClaims); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaims + ); const performanceClient = { startMeasurement: jest.fn(), endMeasurement: jest.fn(), @@ -3802,12 +3713,12 @@ describe("AuthorizationCodeClient unit tests", () => { nonce: idTokenClaims.nonce, }); } catch {} - expect( - createTokenRequestBodySpy.calledWith(authCodeRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + authCodeRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes(`${AADServerParamKeys.X_CLIENT_CURR_TELEM}`) ).toBe(false); @@ -3819,12 +3730,10 @@ describe("AuthorizationCodeClient unit tests", () => { describe("getLogoutUri()", () => { it("Returns a uri", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client = new AuthorizationCodeClient(config); @@ -3843,12 +3752,10 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Returns a uri with given parameters", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client = new AuthorizationCodeClient(config); @@ -3874,22 +3781,19 @@ describe("AuthorizationCodeClient unit tests", () => { }); it("Does not append an extra '?' when the end session endpoint already contains a query string", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromHardcodedValues" - ) - .returns({ - token_endpoint: - "https://login.windows.net/common/oauth2/v2.0/token?param1=value1", - issuer: "https://login.windows.net/{tenantid}/v2.0", - userinfo_endpoint: - "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.windows.net/common/oauth2/v2.0/authorize?param1=value1", - end_session_endpoint: - "https://login.windows.net/common/oauth2/v2.0/logout?param1=value1", - }); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromHardcodedValues" + ).mockReturnValue({ + token_endpoint: + "https://login.windows.net/common/oauth2/v2.0/token?param1=value1", + issuer: "https://login.windows.net/{tenantid}/v2.0", + userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", + authorization_endpoint: + "https://login.windows.net/common/oauth2/v2.0/authorize?param1=value1", + end_session_endpoint: + "https://login.windows.net/common/oauth2/v2.0/logout?param1=value1", + }); const config: ClientConfiguration = await ClientTestUtils.createTestClientConfiguration(); const client = new AuthorizationCodeClient(config); diff --git a/lib/msal-common/test/client/RefreshTokenClient.spec.ts b/lib/msal-common/test/client/RefreshTokenClient.spec.ts index 621e4e1f30..08b9f4bfb9 100644 --- a/lib/msal-common/test/client/RefreshTokenClient.spec.ts +++ b/lib/msal-common/test/client/RefreshTokenClient.spec.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. */ -import sinon from "sinon"; import { AUTHENTICATION_RESULT, DEFAULT_OPENID_CONFIG_RESPONSE, @@ -20,48 +19,48 @@ import { CORS_RESPONSE_HEADERS, TEST_SSH_VALUES, BAD_TOKEN_ERROR_RESPONSE, -} from "../test_kit/StringConstants"; -import { BaseClient } from "../../src/client/BaseClient"; +} from "../test_kit/StringConstants.js"; +import { BaseClient } from "../../src/client/BaseClient.js"; import { GrantType, Constants, CredentialType, AuthenticationScheme, ThrottlingConstants, -} from "../../src/utils/Constants"; -import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys"; -import { ClientTestUtils, MockStorageClass } from "./ClientTestUtils"; -import { Authority } from "../../src/authority/Authority"; -import { RefreshTokenClient } from "../../src/client/RefreshTokenClient"; -import { CommonRefreshTokenRequest } from "../../src/request/CommonRefreshTokenRequest"; -import { AccountEntity } from "../../src/cache/entities/AccountEntity"; -import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity"; -import { AuthenticationResult } from "../../src/response/AuthenticationResult"; -import { AccountInfo } from "../../src/account/AccountInfo"; -import { CacheManager } from "../../src/cache/CacheManager"; -import { ClientConfiguration } from "../../src/config/ClientConfiguration"; -import { CommonSilentFlowRequest } from "../../src/request/CommonSilentFlowRequest"; +} from "../../src/utils/Constants.js"; +import * as AADServerParamKeys from "../../src/constants/AADServerParamKeys.js"; +import { ClientTestUtils, MockStorageClass } from "./ClientTestUtils.js"; +import { Authority } from "../../src/authority/Authority.js"; +import { RefreshTokenClient } from "../../src/client/RefreshTokenClient.js"; +import { CommonRefreshTokenRequest } from "../../src/request/CommonRefreshTokenRequest.js"; +import { AccountEntity } from "../../src/cache/entities/AccountEntity.js"; +import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity.js"; +import { AuthenticationResult } from "../../src/response/AuthenticationResult.js"; +import { AccountInfo } from "../../src/account/AccountInfo.js"; +import { CacheManager } from "../../src/cache/CacheManager.js"; +import { ClientConfiguration } from "../../src/config/ClientConfiguration.js"; +import { CommonSilentFlowRequest } from "../../src/request/CommonSilentFlowRequest.js"; import { ClientAuthErrorCodes, createClientAuthError, -} from "../../src/error/ClientAuthError"; +} from "../../src/error/ClientAuthError.js"; import { ClientConfigurationErrorCodes, createClientConfigurationError, -} from "../../src/error/ClientConfigurationError"; -import { SilentFlowClient } from "../../src/client/SilentFlowClient"; -import { AppMetadataEntity } from "../../src/cache/entities/AppMetadataEntity"; -import { CcsCredentialType } from "../../src/account/CcsCredential"; +} from "../../src/error/ClientConfigurationError.js"; +import { SilentFlowClient } from "../../src/client/SilentFlowClient.js"; +import { AppMetadataEntity } from "../../src/cache/entities/AppMetadataEntity.js"; +import { CcsCredentialType } from "../../src/account/CcsCredential.js"; import { InteractionRequiredAuthError, InteractionRequiredAuthErrorCodes, createInteractionRequiredAuthError, -} from "../../src/error/InteractionRequiredAuthError"; -import { StubPerformanceClient } from "../../src/telemetry/performance/StubPerformanceClient"; -import { ProtocolMode } from "../../src/authority/ProtocolMode"; -import * as TimeUtils from "../../src/utils/TimeUtils"; +} from "../../src/error/InteractionRequiredAuthError.js"; +import { StubPerformanceClient } from "../../src/telemetry/performance/StubPerformanceClient.js"; +import { ProtocolMode } from "../../src/authority/ProtocolMode.js"; +import * as TimeUtils from "../../src/utils/TimeUtils.js"; import { buildAccountFromIdTokenClaims } from "msal-test-utils"; -import { generateCredentialKey } from "../../src/cache/utils/CacheHelpers"; +import { generateCredentialKey } from "../../src/cache/utils/CacheHelpers.js"; const testAccountEntity: AccountEntity = new AccountEntity(); testAccountEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; @@ -98,7 +97,7 @@ const testFamilyRefreshTokenEntity: RefreshTokenEntity = { describe("RefreshTokenClient unit tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); let stubPerformanceClient: StubPerformanceClient; @@ -108,12 +107,10 @@ describe("RefreshTokenClient unit tests", () => { describe("Constructor", () => { it("creates a RefreshTokenClient", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new RefreshTokenClient( @@ -140,31 +137,22 @@ describe("RefreshTokenClient unit tests", () => { }; beforeEach(async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); config = await ClientTestUtils.createTestClientConfiguration(); }); - afterEach(() => { - jest.restoreAllMocks(); - }); - it("Adds tokenQueryParameters to the /token request", (done) => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake(async (url: string) => { - expect(url.includes("/token?testParam=testValue")).toBe( - true - ); - done(); - }); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string) => { + expect(url.includes("/token?testParam=testValue")).toBe(true); + done(); + }); const client = new RefreshTokenClient( config, @@ -189,15 +177,14 @@ describe("RefreshTokenClient unit tests", () => { }); it("Adds tokenBodyParameters to the /token request", (done) => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake(async (url: string, body: string) => { - expect(body).toContain("testParam=testValue"); - done(); - }); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string, body: string) => { + expect(body).toContain("testParam=testValue"); + done(); + }); const client = new RefreshTokenClient(config); @@ -226,12 +213,10 @@ describe("RefreshTokenClient unit tests", () => { config, stubPerformanceClient ); - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); await client.acquireToken(refreshTokenRequest); expect(spy).toHaveBeenCalled(); @@ -244,13 +229,11 @@ describe("RefreshTokenClient unit tests", () => { config, stubPerformanceClient ); - sinon - .stub( - //@ts-ignore - client.networkManager, - "sendPostRequest" - ) - .resolves({ ...AUTHENTICATION_RESULT, headers: {} }); + jest.spyOn( + // @ts-ignore + client.networkManager, + "sendPostRequest" + ).mockResolvedValue({ ...AUTHENTICATION_RESULT, headers: {} }); let refreshTokenSize; await client.acquireToken(refreshTokenRequest).then(() => { @@ -274,17 +257,14 @@ describe("RefreshTokenClient unit tests", () => { config, stubPerformanceClient ); - sinon - .stub( - // @ts-ignore - client.networkManager, - "sendPostRequest" - ) + jest.spyOn( // @ts-ignore - .resolves({ - ...AUTHENTICATION_RESULT_NO_REFRESH_TOKEN, - headers: { ...AUTHENTICATION_RESULT_WITH_HEADERS.headers }, - }); + client.networkManager, + "sendPostRequest" + ).mockResolvedValue({ + ...AUTHENTICATION_RESULT_NO_REFRESH_TOKEN, + headers: { ...AUTHENTICATION_RESULT_WITH_HEADERS.headers }, + }); let refreshTokenSize; await client.acquireToken(refreshTokenRequest).then(() => { @@ -312,20 +292,20 @@ describe("RefreshTokenClient unit tests", () => { testAccount.idToken = TEST_TOKENS.IDTOKEN_V2; beforeEach(async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(Authority.prototype, "getPreferredCache") - .returns("login.windows.net"); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getPreferredCache" + ).mockReturnValue("login.windows.net"); AUTHENTICATION_RESULT.body.client_info = TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO; - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); config = await ClientTestUtils.createTestClientConfiguration(); config.storageInterface!.setAccount(testAccountEntity); @@ -339,36 +319,31 @@ describe("RefreshTokenClient unit tests", () => { client = new RefreshTokenClient(config, stubPerformanceClient); }); - afterEach(() => { - sinon.restore(); - }); - it("Does not add headers that do not qualify for a simple request", (done) => { // For more information about this test see: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake( - async ( - tokenEndpoint: string, - queryString: string, - headers: Record - ) => { - const headerNames = Object.keys(headers); - headerNames.forEach((name) => { - expect( - CORS_SIMPLE_REQUEST_HEADERS.includes( - name.toLowerCase() - ) - ).toBe(true); - }); - - done(); - return AUTHENTICATION_RESULT; - } - ); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockImplementation( + // @ts-expect-error + ( + tokenEndpoint: string, + queryString: string, + headers: Record + ) => { + const headerNames = Object.keys(headers); + headerNames.forEach((name) => { + expect( + CORS_SIMPLE_REQUEST_HEADERS.includes( + name.toLowerCase() + ) + ).toBe(true); + }); + + done(); + return Promise.resolve(AUTHENTICATION_RESULT); + } + ); const client = new RefreshTokenClient( config, @@ -388,13 +363,11 @@ describe("RefreshTokenClient unit tests", () => { }); it("acquires a token", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -434,12 +407,12 @@ describe("RefreshTokenClient unit tests", () => { AUTHENTICATION_RESULT.body.access_token ); expect(authResult.state).toHaveLength(0); - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBe(true); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const result = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const result = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( result.includes(`${TEST_CONFIG.DEFAULT_GRAPH_SCOPE[0]}`) ).toBe(true); @@ -508,26 +481,23 @@ describe("RefreshTokenClient unit tests", () => { }); it("Adds tokenQueryParameters to the /token request", (done) => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string) => { - try { - expect( - url.includes( - "/token?testParam1=testValue1&testParam3=testValue3" - ) - ).toBeTruthy(); - expect( - !url.includes("/token?testParam2=") - ).toBeTruthy(); - done(); - } catch (error) { - done(error); - } - }); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + // @ts-expect-error + ).mockImplementation((url: string) => { + try { + expect( + url.includes( + "/token?testParam1=testValue1&testParam3=testValue3" + ) + ).toBeTruthy(); + expect(!url.includes("/token?testParam2=")).toBeTruthy(); + done(); + } catch (error) { + done(error); + } + }); const client = new RefreshTokenClient( config, @@ -554,12 +524,10 @@ describe("RefreshTokenClient unit tests", () => { }); it("acquireTokenByRefreshToken refreshes a token", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, account: testAccount, @@ -578,24 +546,22 @@ describe("RefreshTokenClient unit tests", () => { type: CcsCredentialType.HOME_ACCOUNT_ID, }, }; - const refreshTokenClientSpy = sinon.spy( + const refreshTokenClientSpy = jest.spyOn( RefreshTokenClient.prototype, "acquireToken" ); await client.acquireTokenByRefreshToken(silentFlowRequest); - expect( - refreshTokenClientSpy.calledWith(expectedRefreshRequest) - ).toBe(true); + expect(refreshTokenClientSpy).toHaveBeenCalledWith( + expectedRefreshRequest + ); }); it("acquireTokenByRefreshToken refreshes a POP token", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(POP_AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(POP_AUTHENTICATION_RESULT); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, account: testAccount, @@ -613,25 +579,23 @@ describe("RefreshTokenClient unit tests", () => { type: CcsCredentialType.HOME_ACCOUNT_ID, }, }; - const refreshTokenClientSpy = sinon.spy( + const refreshTokenClientSpy = jest.spyOn( RefreshTokenClient.prototype, "acquireToken" ); await client.acquireTokenByRefreshToken(silentFlowRequest); - expect(refreshTokenClientSpy.called).toBe(true); - expect( - refreshTokenClientSpy.calledWith(expectedRefreshRequest) - ).toBe(true); + expect(refreshTokenClientSpy).toHaveBeenCalled(); + expect(refreshTokenClientSpy).toHaveBeenCalledWith( + expectedRefreshRequest + ); }); it("acquireTokenByRefreshToken refreshes an SSH Cert", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(SSH_AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(SSH_AUTHENTICATION_RESULT); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, account: testAccount, @@ -650,25 +614,23 @@ describe("RefreshTokenClient unit tests", () => { type: CcsCredentialType.HOME_ACCOUNT_ID, }, }; - const refreshTokenClientSpy = sinon.spy( + const refreshTokenClientSpy = jest.spyOn( RefreshTokenClient.prototype, "acquireToken" ); await client.acquireTokenByRefreshToken(silentFlowRequest); - expect( - refreshTokenClientSpy.calledWith(expectedRefreshRequest) - ).toBe(true); + expect(refreshTokenClientSpy).toHaveBeenCalledWith( + expectedRefreshRequest + ); }); it("does not add claims if none are provided", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -707,12 +669,12 @@ describe("RefreshTokenClient unit tests", () => { AUTHENTICATION_RESULT.body.access_token ); expect(authResult.state).toBe(""); - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBe(true); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const result = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const result = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( result.includes(`${TEST_CONFIG.DEFAULT_GRAPH_SCOPE[0]}`) ).toBe(true); @@ -781,13 +743,11 @@ describe("RefreshTokenClient unit tests", () => { }); it("does not add claims if empty object is provided", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - const createTokenRequestBodySpy = sinon.spy( + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -827,12 +787,12 @@ describe("RefreshTokenClient unit tests", () => { AUTHENTICATION_RESULT.body.access_token ); expect(authResult.state).toBe(""); - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBe(true); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const result = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const result = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( result.includes(`${TEST_CONFIG.DEFAULT_GRAPH_SCOPE[0]}`) ).toBe(true); @@ -901,12 +861,10 @@ describe("RefreshTokenClient unit tests", () => { }); it("includes the requestId in the result when received in server response", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT_WITH_HEADERS); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT_WITH_HEADERS); const client = new RefreshTokenClient( config, stubPerformanceClient @@ -932,12 +890,10 @@ describe("RefreshTokenClient unit tests", () => { }); it("does not include the requestId in the result when none in server response", async () => { - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); const client = new RefreshTokenClient( config, stubPerformanceClient @@ -977,13 +933,11 @@ describe("RefreshTokenClient unit tests", () => { incrementFields: jest.fn(), }; const client = new RefreshTokenClient(config, performanceClient); - sinon - .stub( - // @ts-ignore - client.networkManager, - "sendPostRequest" - ) - .resolves(AUTHENTICATION_RESULT_WITH_HEADERS); + jest.spyOn( + // @ts-ignore + client.networkManager, + "sendPostRequest" + ).mockResolvedValue(AUTHENTICATION_RESULT_WITH_HEADERS); const refreshTokenRequest: CommonRefreshTokenRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, refreshToken: TEST_TOKENS.REFRESH_TOKEN, @@ -995,7 +949,7 @@ describe("RefreshTokenClient unit tests", () => { }; await client.acquireToken(refreshTokenRequest); - expect(performanceClient.addFields).toBeCalledWith( + expect(performanceClient.addFields).toHaveBeenCalledWith( { httpVerToken: "xMsHttpVer", refreshTokenSize: @@ -1023,13 +977,11 @@ describe("RefreshTokenClient unit tests", () => { incrementFields: jest.fn(), }; const client = new RefreshTokenClient(config, performanceClient); - sinon - .stub( - // @ts-ignore - client.networkManager, - "sendPostRequest" - ) - .resolves({ ...AUTHENTICATION_RESULT, headers: {} }); + jest.spyOn( + // @ts-ignore + client.networkManager, + "sendPostRequest" + ).mockResolvedValue({ ...AUTHENTICATION_RESULT, headers: {} }); const refreshTokenRequest: CommonRefreshTokenRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, refreshToken: TEST_TOKENS.REFRESH_TOKEN, @@ -1041,7 +993,7 @@ describe("RefreshTokenClient unit tests", () => { }; await client.acquireToken(refreshTokenRequest); - expect(performanceClient.addFields).toBeCalledWith( + expect(performanceClient.addFields).toHaveBeenCalledWith( { httpVerToken: "", refreshTokenSize: @@ -1062,26 +1014,24 @@ describe("RefreshTokenClient unit tests", () => { testAccount.idToken = TEST_TOKENS.IDTOKEN_V2; beforeEach(async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(Authority.prototype, "getPreferredCache") - .returns("login.windows.net"); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getPreferredCache" + ).mockReturnValue("login.windows.net"); AUTHENTICATION_RESULT_WITH_FOCI.body.client_info = TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO; - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT_WITH_FOCI); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testFamilyRefreshTokenEntity); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT_WITH_FOCI); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testFamilyRefreshTokenEntity); config = await ClientTestUtils.createTestClientConfiguration(); config.storageInterface!.setAccount(testAccountEntity); @@ -1095,12 +1045,8 @@ describe("RefreshTokenClient unit tests", () => { client = new RefreshTokenClient(config, stubPerformanceClient); }); - afterEach(() => { - sinon.restore(); - }); - it("acquires a token (FOCI)", async () => { - const createTokenRequestBodySpy = sinon.spy( + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -1143,12 +1089,12 @@ describe("RefreshTokenClient unit tests", () => { ); expect(authResult.state).toHaveLength(0); - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBe(true); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const result = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const result = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( result.includes(`${TEST_CONFIG.DEFAULT_GRAPH_SCOPE[0]}`) ).toBe(true); @@ -1200,26 +1146,24 @@ describe("RefreshTokenClient unit tests", () => { type: CcsCredentialType.HOME_ACCOUNT_ID, }, }; - const refreshTokenClientSpy = sinon.spy( + const refreshTokenClientSpy = jest.spyOn( RefreshTokenClient.prototype, "acquireToken" ); await client.acquireTokenByRefreshToken(silentFlowRequest); - expect( - refreshTokenClientSpy.calledWith(expectedRefreshRequest) - ).toBe(true); + expect(refreshTokenClientSpy).toHaveBeenCalledWith( + expectedRefreshRequest + ); }); }); describe("Error cases", () => { it("Throws error if account is not included in request object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new RefreshTokenClient( @@ -1243,12 +1187,10 @@ describe("RefreshTokenClient unit tests", () => { }); it("Throws error if request object is null or undefined", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new RefreshTokenClient( @@ -1293,15 +1235,14 @@ describe("RefreshTokenClient unit tests", () => { testAccountEntity.realm = "testTenantId"; testAccountEntity.username = "username@contoso.com"; testAccountEntity.authorityType = "MSSTS"; - sinon - .stub(MockStorageClass.prototype, "getAccount") - .returns(testAccountEntity); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + MockStorageClass.prototype, + "getAccount" + ).mockReturnValue(testAccountEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const tokenRequest: CommonSilentFlowRequest = { scopes: [testScope2], account: testAccount, @@ -1393,12 +1334,10 @@ describe("RefreshTokenClient unit tests", () => { const testAccount: AccountInfo = buildAccountFromIdTokenClaims(ID_TOKEN_CLAIMS).getAccountInfo(); testAccount.idTokenClaims = ID_TOKEN_CLAIMS; - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(BAD_TOKEN_ERROR_RESPONSE); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(BAD_TOKEN_ERROR_RESPONSE); const serverResponse = BAD_TOKEN_ERROR_RESPONSE.body; const invalidGrantAuthError = new InteractionRequiredAuthError( @@ -1452,7 +1391,7 @@ describe("RefreshTokenClient unit tests", () => { TEST_CONFIG.TOKEN_TYPE_BEARER as AuthenticationScheme, }; it("Adds telemetry headers to token request in AAD protocol mode", async () => { - const createTokenRequestBodySpy = sinon.spy( + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -1466,12 +1405,12 @@ describe("RefreshTokenClient unit tests", () => { try { await client.acquireToken(refreshTokenRequest); } catch {} - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes(`${AADServerParamKeys.X_CLIENT_CURR_TELEM}`) ).toBe(true); @@ -1480,7 +1419,7 @@ describe("RefreshTokenClient unit tests", () => { ).toBe(true); }); it("Does not add telemetry headers to token request in OIDC protocol mode", async () => { - const createTokenRequestBodySpy = sinon.spy( + const createTokenRequestBodySpy = jest.spyOn( RefreshTokenClient.prototype, "createTokenRequestBody" ); @@ -1495,12 +1434,12 @@ describe("RefreshTokenClient unit tests", () => { try { await client.acquireToken(refreshTokenRequest); } catch {} - expect( - createTokenRequestBodySpy.calledWith(refreshTokenRequest) - ).toBeTruthy(); + expect(createTokenRequestBodySpy).toHaveBeenCalledWith( + refreshTokenRequest + ); - const returnVal = (await createTokenRequestBodySpy - .returnValues[0]) as string; + const returnVal = (await createTokenRequestBodySpy.mock.results[0] + .value) as string; expect( returnVal.includes(`${AADServerParamKeys.X_CLIENT_CURR_TELEM}`) ).toBe(false); diff --git a/lib/msal-common/test/client/SilentFlowClient.spec.ts b/lib/msal-common/test/client/SilentFlowClient.spec.ts index a41fb8e86f..365915f61f 100644 --- a/lib/msal-common/test/client/SilentFlowClient.spec.ts +++ b/lib/msal-common/test/client/SilentFlowClient.spec.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. */ -import sinon from "sinon"; import { AUTHENTICATION_RESULT, DEFAULT_OPENID_CONFIG_RESPONSE, @@ -12,46 +11,46 @@ import { ID_TOKEN_CLAIMS, TEST_URIS, TEST_TOKENS, -} from "../test_kit/StringConstants"; -import { BaseClient } from "../../src/client/BaseClient"; +} from "../test_kit/StringConstants.js"; +import { BaseClient } from "../../src/client/BaseClient.js"; import { AuthenticationScheme, Constants, CredentialType, ONE_DAY_IN_MS, -} from "../../src/utils/Constants"; +} from "../../src/utils/Constants.js"; import { ClientTestUtils, MockStorageClass, mockCrypto, -} from "./ClientTestUtils"; -import { Authority } from "../../src/authority/Authority"; -import { SilentFlowClient } from "../../src/client/SilentFlowClient"; -import { RefreshTokenClient } from "../../src/client/RefreshTokenClient"; -import { AuthenticationResult } from "../../src/response/AuthenticationResult"; -import { AccountInfo } from "../../src/account/AccountInfo"; -import * as AuthToken from "../../src/account/AuthToken"; -import { AccountEntity } from "../../src/cache/entities/AccountEntity"; -import { IdTokenEntity } from "../../src/cache/entities/IdTokenEntity"; -import { AccessTokenEntity } from "../../src/cache/entities/AccessTokenEntity"; -import * as TimeUtils from "../../src/utils/TimeUtils"; -import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity"; -import { CommonSilentFlowRequest } from "../../src/request/CommonSilentFlowRequest"; -import { CacheManager } from "../../src/cache/CacheManager"; +} from "./ClientTestUtils.js"; +import { Authority } from "../../src/authority/Authority.js"; +import { SilentFlowClient } from "../../src/client/SilentFlowClient.js"; +import { RefreshTokenClient } from "../../src/client/RefreshTokenClient.js"; +import { AuthenticationResult } from "../../src/response/AuthenticationResult.js"; +import { AccountInfo } from "../../src/account/AccountInfo.js"; +import * as AuthToken from "../../src/account/AuthToken.js"; +import { AccountEntity } from "../../src/cache/entities/AccountEntity.js"; +import { IdTokenEntity } from "../../src/cache/entities/IdTokenEntity.js"; +import { AccessTokenEntity } from "../../src/cache/entities/AccessTokenEntity.js"; +import * as TimeUtils from "../../src/utils/TimeUtils.js"; +import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity.js"; +import { CommonSilentFlowRequest } from "../../src/request/CommonSilentFlowRequest.js"; +import { CacheManager } from "../../src/cache/CacheManager.js"; import { ClientAuthErrorCodes, createClientAuthError, -} from "../../src/error/ClientAuthError"; -import { ClientConfiguration } from "../../src/config/ClientConfiguration"; -import { CommonRefreshTokenRequest } from "../../src/request/CommonRefreshTokenRequest"; -import { CcsCredentialType } from "../../src/account/CcsCredential"; -import { ServerTelemetryManager } from "../../src/telemetry/server/ServerTelemetryManager"; +} from "../../src/error/ClientAuthError.js"; +import { ClientConfiguration } from "../../src/config/ClientConfiguration.js"; +import { CommonRefreshTokenRequest } from "../../src/request/CommonRefreshTokenRequest.js"; +import { CcsCredentialType } from "../../src/account/CcsCredential.js"; +import { ServerTelemetryManager } from "../../src/telemetry/server/ServerTelemetryManager.js"; import { InteractionRequiredAuthErrorCodes, createInteractionRequiredAuthError, -} from "../../src/error/InteractionRequiredAuthError"; -import { StubPerformanceClient } from "../../src/telemetry/performance/StubPerformanceClient"; -import { Logger } from "../../src/logger/Logger"; +} from "../../src/error/InteractionRequiredAuthError.js"; +import { StubPerformanceClient } from "../../src/telemetry/performance/StubPerformanceClient.js"; +import { Logger } from "../../src/logger/Logger.js"; import { buildAccountFromIdTokenClaims } from "msal-test-utils"; const testAccountEntity: AccountEntity = @@ -101,7 +100,7 @@ const testRefreshTokenEntity: RefreshTokenEntity = { describe("SilentFlowClient unit tests", () => { afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); const logger = new Logger({}); @@ -113,12 +112,10 @@ describe("SilentFlowClient unit tests", () => { describe("Constructor", () => { it("creates a SilentFlowClient", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); @@ -136,29 +133,30 @@ describe("SilentFlowClient unit tests", () => { ...TEST_CONFIG.DEFAULT_GRAPH_SCOPE, ]; testAccessTokenEntity.target = testScopes.join(" "); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -192,28 +190,29 @@ describe("SilentFlowClient unit tests", () => { ...TEST_CONFIG.DEFAULT_GRAPH_SCOPE, ]; testAccessTokenEntity.target = testScopes.join(" "); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -242,25 +241,26 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireToken returns token from cache if scopes are undefined in request object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const config = await ClientTestUtils.createTestClientConfiguration(); @@ -282,25 +282,26 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireToken returns token from cache if scopes are empty in request object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const config = await ClientTestUtils.createTestClientConfiguration(); @@ -327,28 +328,29 @@ describe("SilentFlowClient unit tests", () => { ...TEST_CONFIG.DEFAULT_GRAPH_SCOPE, ]; testAccessTokenEntity.target = testScopes.join(" "); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -373,24 +375,25 @@ describe("SilentFlowClient unit tests", () => { ...TEST_CONFIG.DEFAULT_GRAPH_SCOPE, ]; testAccessTokenEntity.target = testScopes.join(" "); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient( @@ -403,7 +406,7 @@ describe("SilentFlowClient unit tests", () => { }, stubPerformanceClient ); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -438,37 +441,38 @@ describe("SilentFlowClient unit tests", () => { ...TEST_CONFIG.DEFAULT_GRAPH_SCOPE, ]; testAccessTokenEntity.target = testScopes.join(" "); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const idTokenClaimsWithAuthTime = { ...ID_TOKEN_CLAIMS, auth_time: Date.now() - ONE_DAY_IN_MS * 2, }; - sinon - .stub(AuthToken, "extractTokenClaims") - .returns(idTokenClaimsWithAuthTime); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaimsWithAuthTime + ); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -502,12 +506,10 @@ describe("SilentFlowClient unit tests", () => { describe("Error cases", () => { it("Throws error if account is not included in request object", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); @@ -551,15 +553,14 @@ describe("SilentFlowClient unit tests", () => { testAccountEntity.realm = "testTenantId"; testAccountEntity.username = "username@contoso.com"; testAccountEntity.authorityType = "MSSTS"; - sinon - .stub(MockStorageClass.prototype, "getAccount") - .returns(testAccountEntity); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + MockStorageClass.prototype, + "getAccount" + ).mockReturnValue(testAccountEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); const tokenRequest: CommonSilentFlowRequest = { scopes: [testScope2], account: testAccount, @@ -580,29 +581,30 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireCachedToken throws refresh requiredError if forceRefresh set to true", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -620,28 +622,29 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireCachedToken throws refresh requiredError if access token is expired", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(true); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(true); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -659,28 +662,31 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireCachedToken throws refresh requiredError if access token was cached after the current time", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "wasClockTurnedBack").returns(true); + jest.spyOn(TimeUtils, "wasClockTurnedBack").mockReturnValue( + true + ); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -698,26 +704,29 @@ describe("SilentFlowClient unit tests", () => { }); it("acquireCachedToken throws refresh requiredError if no access token is cached", async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon.stub(CacheManager.prototype, "getAccessToken").returns(null); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(null); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); const config = await ClientTestUtils.createTestClientConfiguration(); const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_SCOPES, @@ -740,41 +749,36 @@ describe("SilentFlowClient unit tests", () => { let client: SilentFlowClient; beforeEach(async () => { - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); AUTHENTICATION_RESULT.body.client_info = TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO; - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); config = await ClientTestUtils.createTestClientConfiguration(); client = new SilentFlowClient(config, stubPerformanceClient); }); - afterEach(() => { - sinon.restore(); - }); - it("acquireToken returns token from cache", async () => { const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -784,14 +788,13 @@ describe("SilentFlowClient unit tests", () => { forceRefresh: false, }; - sinon.stub(TimeUtils, "isTokenExpired").returns(false); - const refreshTokenSpy = sinon.stub( - RefreshTokenClient.prototype, - "acquireToken" - ); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); + const refreshTokenSpy = jest + .spyOn(RefreshTokenClient.prototype, "acquireToken") + .mockImplementation(); const authResult = await client.acquireToken(silentFlowRequest); - expect(refreshTokenSpy.called).toBe(false); + expect(refreshTokenSpy).not.toHaveBeenCalled(); const expectedScopes = testAccessTokenEntity.target.split(" "); expect(authResult.uniqueId).toEqual(ID_TOKEN_CLAIMS.oid); expect(authResult.tenantId).toEqual(ID_TOKEN_CLAIMS.tid); @@ -825,17 +828,17 @@ describe("SilentFlowClient unit tests", () => { }, }; - sinon.stub(TimeUtils, "isTokenExpired").returns(true); - const refreshTokenClientSpy = sinon.spy( + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(true); + const refreshTokenClientSpy = jest.spyOn( RefreshTokenClient.prototype, "acquireToken" ); await client.acquireToken(silentFlowRequest); - expect(refreshTokenClientSpy.called).toBe(true); - expect( - refreshTokenClientSpy.calledWith(expectedRefreshRequest) - ).toBe(true); + expect(refreshTokenClientSpy).toHaveBeenCalled(); + expect(refreshTokenClientSpy).toHaveBeenCalledWith( + expectedRefreshRequest + ); }); it("acquireCachedToken returns cached token", async () => { @@ -852,10 +855,10 @@ describe("SilentFlowClient unit tests", () => { ) ); client = new SilentFlowClient(config, stubPerformanceClient); - const telemetryCacheHitSpy = sinon - .stub(ServerTelemetryManager.prototype, "incrementCacheHits") - .returns(1); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + const telemetryCacheHitSpy = jest + .spyOn(ServerTelemetryManager.prototype, "incrementCacheHits") + .mockReturnValue(1); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -868,7 +871,7 @@ describe("SilentFlowClient unit tests", () => { const response = await client.acquireCachedToken(silentFlowRequest); const authResult: AuthenticationResult = response[0]; const expectedScopes = testAccessTokenEntity.target.split(" "); - expect(telemetryCacheHitSpy.calledOnce).toBe(true); + expect(telemetryCacheHitSpy).toHaveBeenCalledTimes(1); expect(authResult.uniqueId).toEqual(ID_TOKEN_CLAIMS.oid); expect(authResult.tenantId).toEqual(ID_TOKEN_CLAIMS.tid); expect(authResult.scopes).toEqual(expectedScopes); @@ -883,15 +886,15 @@ describe("SilentFlowClient unit tests", () => { it("Throws error if max age is equal to 0 or has transpired since the last end-user authentication", async () => { const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const idTokenClaimsWithAuthTime = { ...ID_TOKEN_CLAIMS, auth_time: Date.now() - ONE_DAY_IN_MS * 2, }; - sinon - .stub(AuthToken, "extractTokenClaims") - .returns(idTokenClaimsWithAuthTime); + jest.spyOn(AuthToken, "extractTokenClaims").mockReturnValue( + idTokenClaimsWithAuthTime + ); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -911,7 +914,7 @@ describe("SilentFlowClient unit tests", () => { it("Throws error if max age is requested and auth time is not included in the token claims", async () => { const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(false); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(false); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -931,7 +934,7 @@ describe("SilentFlowClient unit tests", () => { it("acquireCachedToken throws refresh requiredError if access token is expired", async () => { const client = new SilentFlowClient(config, stubPerformanceClient); - sinon.stub(TimeUtils, "isTokenExpired").returns(true); + jest.spyOn(TimeUtils, "isTokenExpired").mockReturnValue(true); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -949,21 +952,16 @@ describe("SilentFlowClient unit tests", () => { }); it("refreshes token if refreshOn time has passed", async () => { - sinon.restore(); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); AUTHENTICATION_RESULT.body.client_info = TEST_DATA_CLIENT_INFO.TEST_RAW_CLIENT_INFO; - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .resolves(AUTHENTICATION_RESULT); + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ).mockResolvedValue(AUTHENTICATION_RESULT); testAccessTokenEntity.refreshOn = `${ Number(testAccessTokenEntity.cachedAt) - 1 }`; @@ -971,21 +969,25 @@ describe("SilentFlowClient unit tests", () => { Number(testAccessTokenEntity.cachedAt) + AUTHENTICATION_RESULT.body.expires_in }`; - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); - sinon - .stub(MockStorageClass.prototype, "getAccount") - .returns(testAccountEntity); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); + jest.spyOn( + MockStorageClass.prototype, + "getAccount" + ).mockReturnValue(testAccountEntity); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, @@ -1059,15 +1061,14 @@ describe("SilentFlowClient unit tests", () => { }); it("Adds tokenQueryParameters to the /token request", (done) => { - sinon.restore(); AUTHENTICATION_RESULT.body.client_info = TEST_DATA_CLIENT_INFO.TEST_DECODED_CLIENT_INFO; - sinon - .stub( - RefreshTokenClient.prototype, - "executePostToTokenEndpoint" - ) - .callsFake((url: string) => { + jest.spyOn( + RefreshTokenClient.prototype, + "executePostToTokenEndpoint" + ) + // @ts-expect-error + .mockImplementation((url: string) => { try { expect( url.includes( @@ -1084,12 +1085,10 @@ describe("SilentFlowClient unit tests", () => { return error; } }); - sinon - .stub( - Authority.prototype, - "getEndpointMetadataFromNetwork" - ) - .resolves(DEFAULT_OPENID_CONFIG_RESPONSE.body); + jest.spyOn( + Authority.prototype, + "getEndpointMetadataFromNetwork" + ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); testAccessTokenEntity.refreshOn = `${ Number(testAccessTokenEntity.cachedAt) - 1 }`; @@ -1097,21 +1096,25 @@ describe("SilentFlowClient unit tests", () => { Number(testAccessTokenEntity.cachedAt) + AUTHENTICATION_RESULT.body.expires_in }`; - sinon - .stub(CacheManager.prototype, "readAccountFromCache") - .returns(testAccountEntity); - sinon - .stub(CacheManager.prototype, "getIdToken") - .returns(testIdToken); - sinon - .stub(CacheManager.prototype, "getAccessToken") - .returns(testAccessTokenEntity); - sinon - .stub(CacheManager.prototype, "getRefreshToken") - .returns(testRefreshTokenEntity); - sinon - .stub(MockStorageClass.prototype, "getAccount") - .returns(testAccountEntity); + jest.spyOn( + CacheManager.prototype, + "readAccountFromCache" + ).mockReturnValue(testAccountEntity); + jest.spyOn(CacheManager.prototype, "getIdToken").mockReturnValue( + testIdToken + ); + jest.spyOn( + CacheManager.prototype, + "getAccessToken" + ).mockReturnValue(testAccessTokenEntity); + jest.spyOn( + CacheManager.prototype, + "getRefreshToken" + ).mockReturnValue(testRefreshTokenEntity); + jest.spyOn( + MockStorageClass.prototype, + "getAccount" + ).mockReturnValue(testAccountEntity); const silentFlowRequest: CommonSilentFlowRequest = { scopes: TEST_CONFIG.DEFAULT_GRAPH_SCOPE, diff --git a/lib/msal-common/test/response/ResponseHandler.spec.ts b/lib/msal-common/test/response/ResponseHandler.spec.ts index 2298c5f142..41b4062480 100644 --- a/lib/msal-common/test/response/ResponseHandler.spec.ts +++ b/lib/msal-common/test/response/ResponseHandler.spec.ts @@ -1,6 +1,5 @@ -import sinon from "sinon"; -import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse"; -import { ResponseHandler } from "../../src/response/ResponseHandler"; +import { ServerAuthorizationTokenResponse } from "../../src/response/ServerAuthorizationTokenResponse.js"; +import { ResponseHandler } from "../../src/response/ResponseHandler.js"; import { AUTHENTICATION_RESULT, ID_TOKEN_CLAIMS, @@ -14,40 +13,40 @@ import { TEST_TOKEN_LIFETIMES, TEST_TOKENS, TEST_URIS, -} from "../test_kit/StringConstants"; -import { Authority } from "../../src/authority/Authority"; +} from "../test_kit/StringConstants.js"; +import { Authority } from "../../src/authority/Authority.js"; import { INetworkModule, NetworkRequestOptions, -} from "../../src/network/INetworkModule"; -import { ICrypto } from "../../src/crypto/ICrypto"; -import { ServerAuthorizationCodeResponse } from "../../src/response/ServerAuthorizationCodeResponse"; -import { MockStorageClass } from "../client/ClientTestUtils"; -import { TokenClaims } from "../../src/account/TokenClaims"; -import { AccountInfo } from "../../src/account/AccountInfo"; -import { AuthenticationResult } from "../../src/response/AuthenticationResult"; -import { AuthenticationScheme } from "../../src/utils/Constants"; -import { AuthorityOptions } from "../../src/authority/AuthorityOptions"; -import { ProtocolMode } from "../../src/authority/ProtocolMode"; -import { Logger, LogLevel } from "../../src/logger/Logger"; -import * as AuthToken from "../../src/account/AuthToken"; -import { AccountEntity } from "../../src/cache/entities/AccountEntity"; -import { BaseAuthRequest } from "../../src/request/BaseAuthRequest"; -import * as TimeUtils from "../../src/utils/TimeUtils"; -import { AuthError } from "../../src/error/AuthError"; +} from "../../src/network/INetworkModule.js"; +import { ICrypto } from "../../src/crypto/ICrypto.js"; +import { ServerAuthorizationCodeResponse } from "../../src/response/ServerAuthorizationCodeResponse.js"; +import { MockStorageClass } from "../client/ClientTestUtils.js"; +import { TokenClaims } from "../../src/account/TokenClaims.js"; +import { AccountInfo } from "../../src/account/AccountInfo.js"; +import { AuthenticationResult } from "../../src/response/AuthenticationResult.js"; +import { AuthenticationScheme } from "../../src/utils/Constants.js"; +import { AuthorityOptions } from "../../src/authority/AuthorityOptions.js"; +import { ProtocolMode } from "../../src/authority/ProtocolMode.js"; +import { Logger, LogLevel } from "../../src/logger/Logger.js"; +import * as AuthToken from "../../src/account/AuthToken.js"; +import { AccountEntity } from "../../src/cache/entities/AccountEntity.js"; +import { BaseAuthRequest } from "../../src/request/BaseAuthRequest.js"; +import * as TimeUtils from "../../src/utils/TimeUtils.js"; +import { AuthError } from "../../src/error/AuthError.js"; import { ClientAuthError, ClientAuthErrorCodes, -} from "../../src/error/ClientAuthError"; -import { InteractionRequiredAuthError } from "../../src/error/InteractionRequiredAuthError"; -import { ServerError } from "../../src/error/ServerError"; +} from "../../src/error/ClientAuthError.js"; +import { InteractionRequiredAuthError } from "../../src/error/InteractionRequiredAuthError.js"; +import { ServerError } from "../../src/error/ServerError.js"; import { CacheError, CacheErrorCodes, CacheErrorMessages, -} from "../../src/error/CacheError"; -import { CacheManager } from "../../src/cache/CacheManager"; -import { cacheQuotaExceededErrorCode } from "../../src/error/CacheErrorCodes"; +} from "../../src/error/CacheError.js"; +import { CacheManager } from "../../src/cache/CacheManager.js"; +import { cacheQuotaExceededErrorCode } from "../../src/error/CacheErrorCodes.js"; const networkInterface: INetworkModule = { sendGetRequestAsync(url: string, options?: NetworkRequestOptions): T { @@ -189,18 +188,18 @@ const testAuthority = new Authority( ); describe("ResponseHandler.ts", () => { - let preferredCacheStub: sinon.SinonStub; - let claimsStub: sinon.SinonStub; + let preferredCacheStub: jest.SpyInstance; + let claimsStub: jest.SpyInstance; beforeEach(() => { - preferredCacheStub = sinon - .stub(Authority.prototype, "getPreferredCache") - .returns("login.microsoftonline.com"); - claimsStub = sinon - .stub(AuthToken, "extractTokenClaims") - .callsFake((encodedIdToken, crypto) => { + preferredCacheStub = jest + .spyOn(Authority.prototype, "getPreferredCache") + .mockReturnValue("login.microsoftonline.com"); + claimsStub = jest + .spyOn(AuthToken, "extractTokenClaims") + .mockImplementation((encodedIdToken, crypto) => { return ID_TOKEN_CLAIMS as TokenClaims; }); - sinon.stub(AccountEntity.prototype, "getAccountInfo").returns({ + jest.spyOn(AccountEntity.prototype, "getAccountInfo").mockReturnValue({ homeAccountId: TEST_DATA_CLIENT_INFO.TEST_ENCODED_HOME_ACCOUNT_ID, localAccountId: TEST_DATA_CLIENT_INFO.TEST_UID, environment: "login.windows.net", @@ -210,12 +209,12 @@ describe("ResponseHandler.ts", () => { }); afterEach(() => { - sinon.restore(); + jest.restoreAllMocks(); }); describe("generateCacheRecord", () => { it("throws invalid cache environment error", async () => { - preferredCacheStub.returns(""); + preferredCacheStub.mockReturnValue(""); const testRequest: BaseAuthRequest = { authority: testAuthority.canonicalAuthority, correlationId: "CORRELATION_ID", @@ -254,7 +253,7 @@ describe("ResponseHandler.ts", () => { } }); - it("doesn't create AccessTokenEntity if access_token not in response", (done) => { + it("does not create AccessTokenEntity if access_token not in response", (done) => { const testRequest: BaseAuthRequest = { authority: testAuthority.canonicalAuthority, correlationId: "CORRELATION_ID", @@ -291,26 +290,27 @@ describe("ResponseHandler.ts", () => { null ); - sinon - .stub(ResponseHandler, "generateAuthenticationResult") - .callsFake( - async ( - cryptoObj, - authority, - cacheRecord, - request, - idTokenObj, - fromTokenCache, - stateString - ) => { - expect(authority).toBe(testAuthority); - expect(cacheRecord.idToken).not.toBeNull(); - expect(cacheRecord.accessToken).toBeNull(); - expect(cacheRecord.refreshToken).not.toBeNull(); - done(); - return testTokenResponse; - } - ); + jest.spyOn( + ResponseHandler, + "generateAuthenticationResult" + ).mockImplementation( + async ( + cryptoObj, + authority, + cacheRecord, + request, + idTokenObj, + fromTokenCache, + stateString + ) => { + expect(authority).toBe(testAuthority); + expect(cacheRecord.idToken).not.toBeNull(); + expect(cacheRecord.accessToken).toBeNull(); + expect(cacheRecord.refreshToken).not.toBeNull(); + done(); + return testTokenResponse; + } + ); const timestamp = TimeUtils.nowSeconds(); responseHandler.handleServerTokenResponse( testResponse, @@ -320,7 +320,7 @@ describe("ResponseHandler.ts", () => { ); }); - it("doesn't create RefreshTokenEntity if refresh_token not in response", (done) => { + it("does not create RefreshTokenEntity if refresh_token not in response", (done) => { const testRequest: BaseAuthRequest = { authority: testAuthority.canonicalAuthority, correlationId: "CORRELATION_ID", @@ -357,26 +357,27 @@ describe("ResponseHandler.ts", () => { null ); - sinon - .stub(ResponseHandler, "generateAuthenticationResult") - .callsFake( - async ( - cryptoObj, - authority, - cacheRecord, - request, - idTokenObj, - fromTokenCache, - stateString - ) => { - expect(authority).toBe(testAuthority); - expect(cacheRecord.idToken).not.toBeNull(); - expect(cacheRecord.accessToken).not.toBeNull(); - expect(cacheRecord.refreshToken).toBeNull(); - done(); - return testTokenResponse; - } - ); + jest.spyOn( + ResponseHandler, + "generateAuthenticationResult" + ).mockImplementation( + async ( + cryptoObj, + authority, + cacheRecord, + request, + idTokenObj, + fromTokenCache, + stateString + ) => { + expect(authority).toBe(testAuthority); + expect(cacheRecord.idToken).not.toBeNull(); + expect(cacheRecord.accessToken).not.toBeNull(); + expect(cacheRecord.refreshToken).toBeNull(); + done(); + return testTokenResponse; + } + ); const timestamp = TimeUtils.nowSeconds(); responseHandler.handleServerTokenResponse( @@ -422,26 +423,27 @@ describe("ResponseHandler.ts", () => { null ); - sinon - .stub(ResponseHandler, "generateAuthenticationResult") - .callsFake( - async ( - cryptoObj, - authority, - cacheRecord, - request, - idTokenObj, - fromTokenCache, - stateString - ) => { - expect(authority).toBe(testAuthority); - expect(cacheRecord.idToken).not.toBeNull(); - expect(cacheRecord.accessToken).not.toBeNull(); - expect(cacheRecord.refreshToken).not.toBeNull(); - done(); - return testTokenResponse; - } - ); + jest.spyOn( + ResponseHandler, + "generateAuthenticationResult" + ).mockImplementation( + async ( + cryptoObj, + authority, + cacheRecord, + request, + idTokenObj, + fromTokenCache, + stateString + ) => { + expect(authority).toBe(testAuthority); + expect(cacheRecord.idToken).not.toBeNull(); + expect(cacheRecord.accessToken).not.toBeNull(); + expect(cacheRecord.refreshToken).not.toBeNull(); + done(); + return testTokenResponse; + } + ); const timestamp = TimeUtils.nowSeconds(); responseHandler.handleServerTokenResponse( @@ -487,13 +489,9 @@ describe("ResponseHandler.ts", () => { it("should ensure realm property in cached access token if no tenant id is available via claim or authority (OIDC scenario)", (done) => { const { tid, ...tokenClaims } = ID_TOKEN_CLAIMS; - claimsStub.restore(); - - claimsStub = sinon - .stub(AuthToken, "extractTokenClaims") - .callsFake((_encodedIdToken, _crypto) => { - return tokenClaims as TokenClaims; - }); + claimsStub = jest + .spyOn(AuthToken, "extractTokenClaims") + .mockReturnValue(tokenClaims); const testResponse: ServerAuthorizationTokenResponse = { token_type: AuthenticationScheme.BEARER, @@ -537,27 +535,28 @@ describe("ResponseHandler.ts", () => { null ); - sinon - .stub(ResponseHandler, "generateAuthenticationResult") - .callsFake( - async ( - _cryptoObj, - _authority, - cacheRecord, - _fromTokenCache, - _request, - _idTokenClaims, - _requestState, - _serverTokenResponse, - _requestId - ) => { - expect(cacheRecord.accessToken?.realm).toBeDefined(); - - done(); - - return {} as AuthenticationResult; - } - ); + jest.spyOn( + ResponseHandler, + "generateAuthenticationResult" + ).mockImplementation( + async ( + _cryptoObj, + _authority, + cacheRecord, + _fromTokenCache, + _request, + _idTokenClaims, + _requestState, + _serverTokenResponse, + _requestId + ) => { + expect(cacheRecord.accessToken?.realm).toBeDefined(); + + done(); + + return {} as AuthenticationResult; + } + ); responseHandler.handleServerTokenResponse( testResponse, @@ -610,7 +609,7 @@ describe("ResponseHandler.ts", () => { const testResponse: ServerAuthorizationTokenResponse = { ...POP_AUTHENTICATION_RESULT.body, }; - claimsStub.callsFake( + claimsStub.mockImplementation( (encodedToken: string, crypto: ICrypto): TokenClaims | null => { switch (encodedToken) { case testResponse.id_token: @@ -657,7 +656,7 @@ describe("ResponseHandler.ts", () => { const testResponse: ServerAuthorizationTokenResponse = { ...POP_AUTHENTICATION_RESULT.body, }; - claimsStub.callsFake( + claimsStub.mockImplementation( (encodedToken: string, crypto: ICrypto): TokenClaims | null => { switch (encodedToken) { case testResponse.id_token: @@ -726,10 +725,6 @@ describe("ResponseHandler.ts", () => { }); describe("validateServerAuthorizationCodeResponse", () => { - afterEach(() => { - sinon.restore(); - }); - it("throws state mismatch error", (done) => { const testServerCodeResponse: ServerAuthorizationCodeResponse = { code: "testCode", @@ -917,7 +912,7 @@ describe("ResponseHandler.ts", () => { state: TEST_STATE_VALUES.URI_ENCODED_LIB_STATE, }; // Can't spy on buildClientInfo, spy on one of its function calls instead - const buildClientInfoSpy = sinon.spy( + const buildClientInfoSpy = jest.spyOn( cryptoInterface, "base64Decode" ); @@ -934,7 +929,7 @@ describe("ResponseHandler.ts", () => { testServerCodeResponse, TEST_STATE_VALUES.URI_ENCODED_LIB_STATE ); - expect(buildClientInfoSpy.notCalled).toBe(true); + expect(buildClientInfoSpy).not.toHaveBeenCalled(); }); it("throws invalid state error", (done) => { @@ -1120,10 +1115,6 @@ describe("ResponseHandler.ts", () => { }); describe("validateTokenResponse", () => { - afterEach(() => { - sinon.restore(); - }); - it("captures server error no", (done) => { const testTokenResponse: ServerAuthorizationTokenResponse = { error: "test error", @@ -1252,10 +1243,6 @@ describe("ResponseHandler.ts", () => { }); describe("captures cache error", () => { - afterEach(() => { - sinon.restore(); - }); - it("captures cache quota error by checking error code", async () => { const testRequest: BaseAuthRequest = { authority: testAuthority.canonicalAuthority, @@ -1269,10 +1256,10 @@ describe("ResponseHandler.ts", () => { const quotaExceededError = new Error(errorMessage); quotaExceededError.name = "QuotaExceededError"; - sinon - // @ts-ignore - .stub(CacheManager.prototype, "saveAccessToken") - .throws(quotaExceededError); + jest.spyOn( + CacheManager.prototype, + "saveAccessToken" + ).mockRejectedValue(quotaExceededError); const responseHandler = new ResponseHandler( "this-is-a-client-id", @@ -1315,10 +1302,10 @@ describe("ResponseHandler.ts", () => { "Failed to run localstorage.setItem(). Local storage exceeded the quota."; const quotaExceededError = new Error(errorMessage); - sinon - // @ts-ignore - .stub(CacheManager.prototype, "saveAccessToken") - .throws(quotaExceededError); + jest.spyOn( + CacheManager.prototype, + "saveAccessToken" + ).mockRejectedValue(quotaExceededError); const responseHandler = new ResponseHandler( "this-is-a-client-id", @@ -1361,10 +1348,10 @@ describe("ResponseHandler.ts", () => { const error = new Error(errorMessage); error.name = "DummyError"; - sinon - // @ts-ignore - .stub(CacheManager.prototype, "saveAccessToken") - .throws(error); + jest.spyOn( + CacheManager.prototype, + "saveAccessToken" + ).mockRejectedValue(error); const responseHandler = new ResponseHandler( "this-is-a-client-id", @@ -1404,10 +1391,10 @@ describe("ResponseHandler.ts", () => { const errorMessage = "Dummy cache error"; const error = new DOMException(errorMessage); - sinon - // @ts-ignore - .stub(CacheManager.prototype, "saveAccessToken") - .throws(error); + jest.spyOn( + CacheManager.prototype, + "saveAccessToken" + ).mockRejectedValue(error); const responseHandler = new ResponseHandler( "this-is-a-client-id", From 37a0e20c822dc8a8f41b1100b336a3c5725326aa Mon Sep 17 00:00:00 2001 From: Robbie Ginsburg Date: Wed, 25 Sep 2024 14:14:40 -0400 Subject: [PATCH 3/4] Change files --- ...e-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json diff --git a/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json b/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json new file mode 100644 index 0000000000..d3f6df4fa0 --- /dev/null +++ b/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Replaced sinon with jest in all the msal-common tests", + "packageName": "@azure/msal-common", + "email": "rginsburg@microsoft.com", + "dependentChangeType": "none" +} From aea35220e7cad243776fb3a9885bb82c5a29839f Mon Sep 17 00:00:00 2001 From: Robbie Ginsburg Date: Wed, 25 Sep 2024 14:17:19 -0400 Subject: [PATCH 4/4] beachball + minor fixes --- ...-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json | 2 +- lib/msal-common/test/cache/CacheManager.spec.ts | 3 --- lib/msal-common/test/client/BaseClient.spec.ts | 4 ---- lib/msal-common/test/network/ThrottlingUtils.spec.ts | 8 -------- 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json b/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json index d3f6df4fa0..b5bba8d660 100644 --- a/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json +++ b/change/@azure-msal-common-065aa9fc-73b4-479a-95e5-e5141a6b78eb.json @@ -1,6 +1,6 @@ { "type": "none", - "comment": "Replaced sinon with jest in all the msal-common tests", + "comment": "Replaced sinon with jest in all the msal-common tests #7341", "packageName": "@azure/msal-common", "email": "rginsburg@microsoft.com", "dependentChangeType": "none" diff --git a/lib/msal-common/test/cache/CacheManager.spec.ts b/lib/msal-common/test/cache/CacheManager.spec.ts index baa6853cfd..03c2958b67 100644 --- a/lib/msal-common/test/cache/CacheManager.spec.ts +++ b/lib/msal-common/test/cache/CacheManager.spec.ts @@ -936,9 +936,6 @@ describe("CacheManager.ts test cases", () => { }); describe("environment filter", () => { - afterEach(() => { - jest.restoreAllMocks(); - }); it("with configured static cloud discovery metadata", () => { // filter by environment expect( diff --git a/lib/msal-common/test/client/BaseClient.spec.ts b/lib/msal-common/test/client/BaseClient.spec.ts index 0c251bc902..eaed61037c 100644 --- a/lib/msal-common/test/client/BaseClient.spec.ts +++ b/lib/msal-common/test/client/BaseClient.spec.ts @@ -77,10 +77,6 @@ describe("BaseClient.ts Class Unit Tests", () => { ).mockResolvedValue(DEFAULT_OPENID_CONFIG_RESPONSE.body); }); - afterEach(() => { - jest.restoreAllMocks(); - }); - it("Creates default token request headers", async () => { const config = await ClientTestUtils.createTestClientConfiguration(); diff --git a/lib/msal-common/test/network/ThrottlingUtils.spec.ts b/lib/msal-common/test/network/ThrottlingUtils.spec.ts index 44e8131f9b..69cb464471 100644 --- a/lib/msal-common/test/network/ThrottlingUtils.spec.ts +++ b/lib/msal-common/test/network/ThrottlingUtils.spec.ts @@ -34,10 +34,6 @@ describe("ThrottlingUtils", () => { }); describe("preProcess", () => { - afterEach(() => { - jest.restoreAllMocks(); - }); - it("checks the cache and throws an error", () => { const thumbprint: RequestThumbprint = THUMBPRINT; const thumbprintValue: ThrottlingEntity = THROTTLING_ENTITY; @@ -110,10 +106,6 @@ describe("ThrottlingUtils", () => { }); describe("postProcess", () => { - afterEach(() => { - jest.restoreAllMocks(); - }); - it("sets an item in the cache", () => { const thumbprint: RequestThumbprint = THUMBPRINT; const res: NetworkResponse = {