-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor amplify methods to single file (#11881)
- Loading branch information
1 parent
882bc9d
commit 26e7fb4
Showing
17 changed files
with
395 additions
and
279 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,11 @@ import { LoginCognito } from "components"; | |
// utils | ||
import { RouterWrappedComponent } from "utils/testing/setupJest"; | ||
|
||
const mockSignIn = jest.fn(); | ||
jest.mock("aws-amplify/auth", () => ({ | ||
signIn: (credentials: any) => mockSignIn(credentials), | ||
const mockLoginUser = jest.fn(); | ||
|
||
jest.mock("utils", () => ({ | ||
loginUser: (username: string, password: string) => | ||
mockLoginUser(username, password), | ||
})); | ||
|
||
const mockUseNavigate = jest.fn(); | ||
|
@@ -30,12 +32,9 @@ describe("Test LoginCognito", () => { | |
const passwordInput = screen.getByLabelText("Password"); | ||
const submitButton = screen.getByRole("button"); | ||
await userEvent.type(emailInput, "[email protected]"); | ||
await userEvent.type(passwordInput, "p@$$w0rd"); //pragma: allowlist secret | ||
await userEvent.type(passwordInput, "test"); | ||
await userEvent.click(submitButton); | ||
expect(mockSignIn).toHaveBeenCalledWith({ | ||
username: "[email protected]", | ||
password: "p@$$w0rd", //pragma: allowlist secret | ||
}); | ||
expect(mockLoginUser).toHaveBeenCalledWith("[email protected]", "test"); | ||
expect(mockUseNavigate).toHaveBeenCalledWith("/"); | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import { | ||
authenticateWithIDM, | ||
del, | ||
get, | ||
getRequestHeaders, | ||
getTokens, | ||
loginUser, | ||
logoutUser, | ||
post, | ||
put, | ||
refreshSession, | ||
} from "utils"; | ||
|
||
const mockResponse = (method?: string) => ({ | ||
response: { body: { json: () => ({ test: method }) } }, | ||
}); | ||
const mockDelete = jest.fn().mockImplementation(() => mockResponse()); | ||
const mockGet = jest.fn().mockImplementation(() => mockResponse("get")); | ||
const mockPost = jest.fn().mockImplementation(() => mockResponse("post")); | ||
const mockPut = jest.fn().mockImplementation(() => mockResponse("put")); | ||
const mockSession = jest.fn(); | ||
const mockSignInWithRedirect = jest.fn(); | ||
const mockSignIn = jest.fn(); | ||
const mockSignOut = jest.fn(); | ||
const mockTimeout = jest.fn(); | ||
|
||
jest.mock("aws-amplify/api", () => ({ | ||
del: () => mockDelete(), | ||
get: () => mockGet(), | ||
post: () => mockPost(), | ||
put: () => mockPut(), | ||
})); | ||
|
||
jest.mock("aws-amplify/auth", () => ({ | ||
fetchAuthSession: () => mockSession(), | ||
signIn: () => mockSignIn(), | ||
signOut: () => mockSignOut(), | ||
signInWithRedirect: () => mockSignInWithRedirect(), | ||
})); | ||
|
||
jest.mock("utils/auth/authLifecycle", () => ({ | ||
updateTimeout: () => mockTimeout(), | ||
})); | ||
|
||
describe("utils/api/apiLib", () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe("getRequestHeaders()", () => { | ||
test("Logs error to console if Auth throws error", async () => { | ||
jest.spyOn(console, "log").mockImplementation(jest.fn()); | ||
const spy = jest.spyOn(console, "log"); | ||
|
||
mockSession.mockImplementation(() => { | ||
throw new Error(); | ||
}); | ||
|
||
await getRequestHeaders(); | ||
|
||
expect(spy).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("Returns token if current idToken exists", async () => { | ||
mockSession.mockResolvedValue({ | ||
tokens: { | ||
idToken: { | ||
toString: () => "stringToken", | ||
}, | ||
}, | ||
}); | ||
|
||
const result = await getRequestHeaders(); | ||
|
||
expect(result).toStrictEqual({ "x-api-key": "stringToken" }); | ||
}); | ||
}); | ||
|
||
test("getTokens()", async () => { | ||
await getTokens(); | ||
expect(mockSession).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("authenticateWithIDM()", async () => { | ||
await authenticateWithIDM(); | ||
expect(mockSignInWithRedirect).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("loginUser()", async () => { | ||
await loginUser("[email protected]", "test"); | ||
expect(mockSignIn).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("logoutUser()", async () => { | ||
await logoutUser(); | ||
expect(mockSignOut).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("refreshSession()", async () => { | ||
await refreshSession(); | ||
expect(mockSession).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("del()", async () => { | ||
const test = async () => await del("/del"); | ||
await expect(test()).resolves.toBeUndefined(); | ||
expect(mockDelete).toHaveBeenCalledTimes(1); | ||
expect(mockTimeout).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("get()", async () => { | ||
const test = async () => await get<string>("/get"); | ||
await expect(test()).resolves.toEqual({ test: "get" }); | ||
expect(mockGet).toHaveBeenCalledTimes(1); | ||
expect(mockTimeout).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("post()", async () => { | ||
const test = async () => await post<string>("/post"); | ||
await expect(test()).resolves.toEqual({ test: "post" }); | ||
expect(mockPost).toHaveBeenCalledTimes(1); | ||
expect(mockTimeout).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("put()", async () => { | ||
const test = async () => await put<string>("/put"); | ||
await expect(test()).resolves.toEqual({ test: "put" }); | ||
expect(mockPut).toHaveBeenCalledTimes(1); | ||
expect(mockTimeout).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test("API error throws with response info", async () => { | ||
jest.spyOn(console, "log").mockImplementation(jest.fn()); | ||
const spy = jest.spyOn(console, "log"); | ||
|
||
mockGet.mockImplementationOnce(() => { | ||
throw { | ||
response: { | ||
body: "Error Info", | ||
}, | ||
}; | ||
}); | ||
|
||
await expect(get("/get")).rejects.toThrow( | ||
"Request Failed - /get - Error Info" | ||
); | ||
expect(spy).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
test("API error throws without response info", async () => { | ||
jest.spyOn(console, "log").mockImplementation(jest.fn()); | ||
const spy = jest.spyOn(console, "log"); | ||
|
||
mockPost.mockImplementationOnce(() => { | ||
throw "String Error"; | ||
}); | ||
|
||
await expect(post("/post")).rejects.toThrow( | ||
"Request Failed - /post - undefined" | ||
); | ||
expect(spy).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* eslint-disable no-console */ | ||
|
||
import { | ||
del as ampDel, | ||
get as ampGet, | ||
post as ampPost, | ||
put as ampPut, | ||
} from "aws-amplify/api"; | ||
import { | ||
AuthTokens, | ||
fetchAuthSession, | ||
signIn, | ||
signInWithRedirect, | ||
signOut, | ||
} from "aws-amplify/auth"; | ||
import { updateTimeout } from "utils"; | ||
|
||
const apiName = "mcr"; | ||
|
||
interface RequestHeaders { | ||
"x-api-key": string | undefined; | ||
} | ||
|
||
interface RequestOptions { | ||
body: any; | ||
} | ||
|
||
export async function getRequestHeaders(): Promise<RequestHeaders | undefined> { | ||
try { | ||
const tokens = await getTokens(); | ||
const headers = { | ||
"x-api-key": tokens?.idToken?.toString(), | ||
}; | ||
|
||
return headers; | ||
} catch (error) { | ||
console.log(error); | ||
return; | ||
} | ||
} | ||
|
||
export async function getTokens(): Promise<AuthTokens | undefined> { | ||
return (await fetchAuthSession()).tokens; | ||
} | ||
|
||
export async function authenticateWithIDM(): Promise<void> { | ||
await signInWithRedirect({ provider: { custom: "Okta" } }); | ||
} | ||
|
||
export async function loginUser( | ||
username: string, | ||
password: string | ||
): Promise<void> { | ||
await signIn({ username, password }); | ||
} | ||
|
||
export async function logoutUser(): Promise<void> { | ||
await signOut(); | ||
} | ||
|
||
export async function refreshSession(): Promise<void> { | ||
await fetchAuthSession({ forceRefresh: true }); | ||
} | ||
|
||
export async function apiRequest<T>( | ||
request: any, | ||
path: string, | ||
opts?: RequestOptions, | ||
hasResponseBody?: Boolean | ||
): Promise<T> { | ||
const requestHeaders = await getRequestHeaders(); | ||
const options = { | ||
headers: { ...requestHeaders }, | ||
...opts, | ||
}; | ||
|
||
try { | ||
await updateTimeout(); | ||
|
||
if (!hasResponseBody) { | ||
await request({ apiName, path, options }).response; | ||
return undefined as unknown as T; | ||
} | ||
|
||
const { body } = await request({ apiName, path, options }).response; | ||
return (await body.json()) as unknown as T; | ||
} catch (e: any) { | ||
const info = `Request Failed - ${path} - ${e.response?.body}`; | ||
console.log(e); | ||
console.log(info); | ||
throw new Error(info); | ||
} | ||
} | ||
|
||
export async function del<T>(path: string, opts?: RequestOptions): Promise<T> { | ||
return apiRequest<T>(ampDel, path, opts, false); | ||
} | ||
|
||
export async function get<T>(path: string, opts?: RequestOptions): Promise<T> { | ||
return apiRequest<T>(ampGet, path, opts, true); | ||
} | ||
|
||
export async function post<T>(path: string, opts?: RequestOptions): Promise<T> { | ||
return apiRequest<T>(ampPost, path, opts, true); | ||
} | ||
|
||
export async function put<T>(path: string, opts?: RequestOptions): Promise<T> { | ||
return apiRequest<T>(ampPut, path, opts, true); | ||
} |
Oops, something went wrong.