diff --git a/.changeset/light-kiwis-teach.md b/.changeset/light-kiwis-teach.md new file mode 100644 index 00000000000..154aeba940b --- /dev/null +++ b/.changeset/light-kiwis-teach.md @@ -0,0 +1,5 @@ +--- +"@smithy/shared-ini-file-loader": minor +--- + +add mock controls to file loader diff --git a/packages/shared-ini-file-loader/src/externalDataInterceptor.spec.ts b/packages/shared-ini-file-loader/src/externalDataInterceptor.spec.ts new file mode 100644 index 00000000000..fb559a5ebf5 --- /dev/null +++ b/packages/shared-ini-file-loader/src/externalDataInterceptor.spec.ts @@ -0,0 +1,27 @@ +import { describe, expect, test as it } from "vitest"; + +import { externalDataInterceptor } from "./externalDataInterceptor"; +import { getSSOTokenFromFile } from "./getSSOTokenFromFile"; +import { slurpFile } from "./slurpFile"; + +describe("fileMockController", () => { + it("intercepts slurpFile", async () => { + externalDataInterceptor.interceptFile("abcd", "contents"); + + expect(await slurpFile("abcd")).toEqual("contents"); + expect(externalDataInterceptor.getFileRecord()).toEqual({ + abcd: Promise.resolve("contents"), + }); + expect(await externalDataInterceptor.getFileRecord().abcd).toEqual("contents"); + }); + + it("intercepts getSSOTokenFromFile", async () => { + externalDataInterceptor.interceptToken("TOKEN", "token-contents"); + + expect(await getSSOTokenFromFile("TOKEN")).toEqual("token-contents"); + + expect(externalDataInterceptor.getTokenRecord()).toEqual({ + TOKEN: "token-contents", + }); + }); +}); diff --git a/packages/shared-ini-file-loader/src/externalDataInterceptor.ts b/packages/shared-ini-file-loader/src/externalDataInterceptor.ts new file mode 100644 index 00000000000..3aa898338b6 --- /dev/null +++ b/packages/shared-ini-file-loader/src/externalDataInterceptor.ts @@ -0,0 +1,20 @@ +import { tokenIntercept } from "./getSSOTokenFromFile"; +import { fileIntercept } from "./slurpFile"; + +/** + * @internal + */ +export const externalDataInterceptor = { + getFileRecord() { + return fileIntercept; + }, + interceptFile(path: string, contents: string) { + fileIntercept[path] = Promise.resolve(contents); + }, + getTokenRecord() { + return tokenIntercept; + }, + interceptToken(id: string, contents: any) { + tokenIntercept[id] = contents; + }, +}; diff --git a/packages/shared-ini-file-loader/src/getSSOTokenFromFile.ts b/packages/shared-ini-file-loader/src/getSSOTokenFromFile.ts index 80955c7aaf0..e0341d49322 100644 --- a/packages/shared-ini-file-loader/src/getSSOTokenFromFile.ts +++ b/packages/shared-ini-file-loader/src/getSSOTokenFromFile.ts @@ -53,12 +53,20 @@ export interface SSOToken { startUrl?: string; } +/** + * @internal + */ +export const tokenIntercept = {} as Record; + /** * @internal * @param id - can be either a start URL or the SSO session name. * Returns the SSO token from the file system. */ export const getSSOTokenFromFile = async (id: string) => { + if (tokenIntercept[id]) { + return tokenIntercept[id]; + } const ssoTokenFilepath = getSSOTokenFilepath(id); const ssoTokenText = await readFile(ssoTokenFilepath, "utf8"); return JSON.parse(ssoTokenText) as SSOToken; diff --git a/packages/shared-ini-file-loader/src/index.ts b/packages/shared-ini-file-loader/src/index.ts index 3e8b2c7470d..33cd617c627 100644 --- a/packages/shared-ini-file-loader/src/index.ts +++ b/packages/shared-ini-file-loader/src/index.ts @@ -1,8 +1,9 @@ export * from "./getHomeDir"; export * from "./getProfileName"; export * from "./getSSOTokenFilepath"; -export * from "./getSSOTokenFromFile"; +export { getSSOTokenFromFile, SSOToken } from "./getSSOTokenFromFile"; export * from "./loadSharedConfigFiles"; export * from "./loadSsoSessionData"; export * from "./parseKnownFiles"; +export { externalDataInterceptor } from "./externalDataInterceptor"; export * from "./types"; diff --git a/packages/shared-ini-file-loader/src/slurpFile.ts b/packages/shared-ini-file-loader/src/slurpFile.ts index 74f017d470e..7f63e860065 100644 --- a/packages/shared-ini-file-loader/src/slurpFile.ts +++ b/packages/shared-ini-file-loader/src/slurpFile.ts @@ -3,13 +3,17 @@ import { promises as fsPromises } from "fs"; const { readFile } = fsPromises; -const filePromisesHash: Record> = {}; +export const filePromisesHash: Record> = {}; +export const fileIntercept: Record> = {}; interface SlurpFileOptions { ignoreCache?: boolean; } export const slurpFile = (path: string, options?: SlurpFileOptions) => { + if (fileIntercept[path] !== undefined) { + return fileIntercept[path]; + } if (!filePromisesHash[path] || options?.ignoreCache) { filePromisesHash[path] = readFile(path, "utf8"); }