mirror of
https://github.com/teamhanko/hanko.git
synced 2025-10-28 06:37:57 +08:00
142 lines
4.9 KiB
TypeScript
142 lines
4.9 KiB
TypeScript
import {
|
|
PasswordClient,
|
|
InvalidPasswordError,
|
|
TooManyRequestsError,
|
|
TechnicalError,
|
|
} from "../../../src";
|
|
import { Response } from "../../../src/lib/client/HttpClient";
|
|
|
|
const userID = "test-user-1";
|
|
const password = "test-password-1";
|
|
const passwordRetryAfter = 180;
|
|
let passwordClient: PasswordClient;
|
|
|
|
beforeEach(() => {
|
|
passwordClient = new PasswordClient("http://test.api");
|
|
});
|
|
|
|
describe("PasswordClient.login()", () => {
|
|
it("should do a password login", async () => {
|
|
const response = new Response(new XMLHttpRequest());
|
|
response.ok = true;
|
|
jest.spyOn(passwordClient.client, "post").mockResolvedValue(response);
|
|
jest.spyOn(passwordClient.passcodeState, "read");
|
|
jest.spyOn(passwordClient.passcodeState, "reset");
|
|
jest.spyOn(passwordClient.passcodeState, "write");
|
|
|
|
const loginResponse = passwordClient.login(userID, password);
|
|
await expect(loginResponse).resolves.toBeUndefined();
|
|
expect(passwordClient.passcodeState.read).toHaveBeenCalledTimes(1);
|
|
expect(passwordClient.passcodeState.reset).toHaveBeenCalledWith(userID);
|
|
expect(passwordClient.passcodeState.write).toHaveBeenCalledTimes(1);
|
|
expect(passwordClient.client.post).toHaveBeenCalledWith("/password/login", {
|
|
user_id: userID,
|
|
password,
|
|
});
|
|
});
|
|
|
|
it("should throw error when using an invalid password", async () => {
|
|
const response = new Response(new XMLHttpRequest());
|
|
response.status = 401;
|
|
jest.spyOn(passwordClient.client, "post").mockResolvedValue(response);
|
|
|
|
const loginResponse = passwordClient.login(userID, password);
|
|
await expect(loginResponse).rejects.toThrow(InvalidPasswordError);
|
|
});
|
|
|
|
it("should throw error and set retry after in state on too many request response from API", async () => {
|
|
const xhr = new XMLHttpRequest();
|
|
const response = new Response(xhr);
|
|
|
|
response.status = 429;
|
|
|
|
jest.spyOn(passwordClient.client, "post").mockResolvedValue(response);
|
|
jest
|
|
.spyOn(response.headers, "get")
|
|
.mockReturnValue(`${passwordRetryAfter}`);
|
|
jest.spyOn(passwordClient.passwordState, "read");
|
|
jest.spyOn(passwordClient.passwordState, "setRetryAfter");
|
|
jest.spyOn(passwordClient.passwordState, "write");
|
|
|
|
await expect(passwordClient.login(userID, password)).rejects.toThrowError(
|
|
TooManyRequestsError
|
|
);
|
|
|
|
expect(passwordClient.passwordState.read).toHaveBeenCalledTimes(1);
|
|
expect(passwordClient.passwordState.setRetryAfter).toHaveBeenCalledWith(
|
|
userID,
|
|
passwordRetryAfter
|
|
);
|
|
expect(passwordClient.passwordState.write).toHaveBeenCalledTimes(1);
|
|
expect(response.headers.get).toHaveBeenCalledWith("Retry-After");
|
|
});
|
|
|
|
it("should throw error when API response is not ok", async () => {
|
|
const response = new Response(new XMLHttpRequest());
|
|
passwordClient.client.post = jest.fn().mockResolvedValue(response);
|
|
|
|
const loginResponse = passwordClient.login(userID, password);
|
|
await expect(loginResponse).rejects.toThrowError(TechnicalError);
|
|
});
|
|
|
|
it("should throw error on API communication failure", async () => {
|
|
passwordClient.client.post = jest
|
|
.fn()
|
|
.mockRejectedValue(new Error("Test error"));
|
|
|
|
const loginResponse = passwordClient.login(userID, password);
|
|
await expect(loginResponse).rejects.toThrowError("Test error");
|
|
});
|
|
});
|
|
|
|
describe("PasswordClient.update()", () => {
|
|
it("should update a password", async () => {
|
|
const response = new Response(new XMLHttpRequest());
|
|
response.ok = true;
|
|
jest.spyOn(passwordClient.client, "put").mockResolvedValue(response);
|
|
|
|
const loginResponse = passwordClient.update(userID, password);
|
|
await expect(loginResponse).resolves.toBeUndefined();
|
|
|
|
expect(passwordClient.client.put).toHaveBeenCalledWith("/password", {
|
|
user_id: userID,
|
|
password,
|
|
});
|
|
});
|
|
|
|
it.each`
|
|
status | error
|
|
${401} | ${"Unauthorized error"}
|
|
${500} | ${"Technical error"}
|
|
`(
|
|
"should throw error when API response is not ok",
|
|
async ({ status, error }) => {
|
|
const response = new Response(new XMLHttpRequest());
|
|
response.ok = status >= 200 && status <= 299;
|
|
response.status = status;
|
|
passwordClient.client.put = jest.fn().mockResolvedValue(response);
|
|
|
|
const config = passwordClient.update(userID, password);
|
|
await expect(config).rejects.toThrowError(error);
|
|
}
|
|
);
|
|
|
|
it("should throw error on API communication failure", async () => {
|
|
passwordClient.client.put = jest
|
|
.fn()
|
|
.mockRejectedValue(new Error("Test error"));
|
|
|
|
const config = passwordClient.update(userID, password);
|
|
await expect(config).rejects.toThrowError("Test error");
|
|
});
|
|
|
|
describe("PasswordClient.getRetryAfter()", () => {
|
|
it("should return password resend after seconds", async () => {
|
|
jest
|
|
.spyOn(passwordClient.passwordState, "getRetryAfter")
|
|
.mockReturnValue(passwordRetryAfter);
|
|
expect(passwordClient.getRetryAfter(userID)).toEqual(passwordRetryAfter);
|
|
});
|
|
});
|
|
});
|