[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant-backoffice] 01/11: bank: implement login
From: |
gnunet |
Subject: |
[taler-merchant-backoffice] 01/11: bank: implement login |
Date: |
Mon, 20 Dec 2021 17:44:59 +0100 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository merchant-backoffice.
commit 6924c5d75e6db30c7fad9b762f23fb6d78c95700
Author: ms <ms@taler.net>
AuthorDate: Fri Dec 17 23:04:25 2021 +0100
bank: implement login
---
packages/bank/src/pages/home/index.tsx | 92 +++++++++++++++++++++++++------
packages/bank/tests/__tests__/homepage.js | 55 ++++++++++++++----
2 files changed, 120 insertions(+), 27 deletions(-)
diff --git a/packages/bank/src/pages/home/index.tsx
b/packages/bank/src/pages/home/index.tsx
index 9ed70ea..04f01cb 100644
--- a/packages/bank/src/pages/home/index.tsx
+++ b/packages/bank/src/pages/home/index.tsx
@@ -21,7 +21,7 @@ interface BackendStateType {
/**
* Request body of /register.
*/
-interface RegistrationRequestType {
+interface CredentialsRequestType {
username: string;
password: string;
}
@@ -181,6 +181,34 @@ async function createWithdrawalOperation(
}
}
+async function loginCall(
+ req: CredentialsRequestType,
+ /**
+ * FIXME: figure out if the two following
+ * functions can be retrieved somewhat from
+ * the state.
+ */
+ backendStateSetter: StateUpdater<BackendStateTypeOpt>,
+ pageStateSetter: StateUpdater<PageStateType>
+) {
+
+ /**
+ * Optimistically setting the state as 'logged in', and
+ * let the Account component request the balance to check
+ * whether the credentials are valid. If not, then Account
+ * will switch the state back to 'logged out' (and the user
+ * will see again the login/register form).
+ */
+ pageStateSetter((prevState) => ({ ...prevState, isLoggedIn: true }));
+ backendStateSetter((prevState) => ({
+ ...prevState,
+ url: getRootPath(),
+ username: req.username,
+ password: req.password,
+ }));
+}
+
+
/**
* This function requests /register.
*
@@ -189,7 +217,7 @@ async function createWithdrawalOperation(
* the page's (to indicate a successful login or a problem).
*/
async function registrationCall(
- req: RegistrationRequestType,
+ req: CredentialsRequestType,
/**
* FIXME: figure out if the two following
* functions can be retrieved somewhat from
@@ -213,8 +241,13 @@ async function registrationCall(
return;
}
if (!res.ok) {
+ const errorRaw = await res.text();
console.log(`New registration gave response error (${res.status})`,
res.statusText);
- pageStateSetter((prevState) => ({ ...prevState, hasError: true }));
+ pageStateSetter((prevState) => ({
+ ...prevState,
+ hasError: true,
+ error: errorRaw
+ }));
} else {
console.log("Credentials are valid");
pageStateSetter((prevState) => ({ ...prevState, isLoggedIn: true }));
@@ -237,8 +270,20 @@ async function registrationCall(
function Account(props: any) {
const { talerWithdrawUri, accountLabel } = props;
const { data, error } = useSWR(`accounts/${props.accountLabel}`);
- if (typeof error != "undefined") {
- return <p>Account information could not be retrieved</p>
+ console.log("account data", data);
+ console.log("account error", error);
+ if (typeof error !== "undefined") {
+ switch(error.status) {
+ case 404: {
+ return <p>Username was not found</p>
+ }
+ case 401: {
+ return <p>Wrong credentials given</p>
+ }
+ default: {
+ return <p>Account information could not be retrieved.</p>
+ }
+ }
}
if (!data) return <p>Retrieving the profile page...</p>;
/**
@@ -274,7 +319,14 @@ function SWRWithCredentials(props: any): VNode {
<SWRConfig
value={{
fetcher: (url) =>
- fetch(backendUrl + url || "", { headers: headers }).then((r) =>
r.json()),
+ fetch(backendUrl + url || "", { headers: headers }).then(
+ (r) => {
+ if (!r.ok) {
+ throw {status: r.status, json: r.json()};
+ }
+ return r.json()
+ }
+ ),
}}
>
{props.children}
@@ -337,17 +389,16 @@ export function BankHome(): VNode {
*/
}
- var registrationData: RegistrationRequestType;
+ var submitData: CredentialsRequestType;
return (
<div>
- <p>Sign up!</p>
<input
type="text"
placeholder="username"
required
onInput={(e): void => {
- registrationData = {
- ...registrationData,
+ submitData = {
+ ...submitData,
username: e.currentTarget.value,
};
}}
@@ -357,8 +408,8 @@ export function BankHome(): VNode {
placeholder="password"
required
onInput={(e): void => {
- registrationData = {
- ...registrationData,
+ submitData = {
+ ...submitData,
password: e.currentTarget.value,
};
}}
@@ -367,13 +418,22 @@ export function BankHome(): VNode {
<button
onClick={() => {
registrationCall(
- registrationData,
+ submitData,
backendStateSetter,
pageStateSetter
);
- }}
- >
- Submit
+ }}>
+ Sign up
+ </button>
+ <button
+ onClick={() => {
+ loginCall(
+ submitData,
+ backendStateSetter,
+ pageStateSetter
+ );
+ }}>
+ Sign in
</button>
</div>
);
diff --git a/packages/bank/tests/__tests__/homepage.js
b/packages/bank/tests/__tests__/homepage.js
index 03a909d..46c6ae8 100644
--- a/packages/bank/tests/__tests__/homepage.js
+++ b/packages/bank/tests/__tests__/homepage.js
@@ -16,14 +16,19 @@ import fetchMock from "jest-fetch-mock";
*
* Return the username and the submit button.
*/
-function fillRegistrationForm() {
+function fillCredentialsForm() {
const username = Math.random().toString().substring(2);
const u = screen.getByPlaceholderText("username");
const p = screen.getByPlaceholderText("password");
fireEvent.input(u, {target: {value: username}})
fireEvent.input(p, {target: {value: "bar"}})
- const submitButton = screen.getByText("Submit");
- return {username: username, submitButton: submitButton};
+ const signupButton = screen.getByText("Sign up");
+ const signinButton = screen.getByText("Sign in");
+ return {
+ username: username,
+ signupButton: signupButton,
+ signinButton: signinButton
+ };
}
fetchMock.enableMocks();
@@ -36,7 +41,7 @@ describe("withdraw", () => {
// Register and land on the profile page.
beforeEach(() => {
render(<BankHome />);
- const { username, submitButton } = fillRegistrationForm();
+ const { username, signupButton } = fillCredentialsForm();
fetch.once("{}", {
status: 200
}).once(JSON.stringify({
@@ -46,7 +51,7 @@ describe("withdraw", () => {
},
paytoUri: "payto://iban/123/ABC"
}))
- fireEvent.click(submitButton);
+ fireEvent.click(signupButton);
})
test("network failure before withdrawal creation", async () => {
@@ -84,9 +89,9 @@ describe("home page", () => {
test("new registration response error 404", async () => {
render(<BankHome />);
- let { username, submitButton } = fillRegistrationForm();
+ let { username, signupButton } = fillCredentialsForm();
fetch.mockResponseOnce("Not found", {status: 404})
- fireEvent.click(submitButton);
+ fireEvent.click(signupButton);
await screen.findByText("has a problem", {exact: false});
expect(fetch).toHaveBeenCalledWith(
"http://localhost/testing/register",
@@ -96,10 +101,10 @@ describe("home page", () => {
test("registration network failure", async () => {
render(<BankHome />);
- const { username, submitButton } = fillRegistrationForm();
+ const { username, signupButton } = fillCredentialsForm();
// Mocking network failure.
fetch.mockReject("API is down");
- fireEvent.click(submitButton);
+ fireEvent.click(signupButton);
await screen.findByText("has a problem", {exact: false});
expect(fetch).toHaveBeenCalledWith(
"http://localhost/testing/register",
@@ -107,9 +112,37 @@ describe("home page", () => {
)
})
+ test("login non existent user", async () => {
+ render(<BankHome />);
+ const { username, signinButton } = fillCredentialsForm();
+ fetch.once("{}", {status: 404});
+ fireEvent.click(signinButton);
+ await screen.findByText("username was not found", {exact: false})
+ })
+ test("login wrong credentials", async () => {
+ render(<BankHome />);
+ const { username, signinButton } = fillCredentialsForm();
+ fetch.once("{}", {status: 401});
+ fireEvent.click(signinButton);
+ await screen.findByText("wrong credentials given", {exact: false})
+ })
+ test("login success", async () => {
+ render(<BankHome />);
+ const { username, signinButton } = fillCredentialsForm();
+ fetch.once(JSON.stringify({
+ balance: {
+ amount: "EUR:10",
+ credit_debit_indicator: "credit"
+ },
+ paytoUri: "payto://iban/123/ABC"
+ }))
+ fireEvent.click(signinButton);
+ await screen.findByText("balance is EUR:10", {exact: false})
+ })
+
test("registration success", async () => {
render(<BankHome />);
- const { username, submitButton } = fillRegistrationForm();
+ const { username, signupButton } = fillCredentialsForm();
/**
* Mock successful registration and balance request.
*/
@@ -122,7 +155,7 @@ describe("home page", () => {
},
paytoUri: "payto://iban/123/ABC"
}))
- fireEvent.click(submitButton);
+ fireEvent.click(signupButton);
/**
* Tests that a balance is shown after the successful
* registration.
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-merchant-backoffice] branch master updated (aa05541 -> 8003d41), gnunet, 2021/12/20
- [taler-merchant-backoffice] 03/11: bank tests, gnunet, 2021/12/20
- [taler-merchant-backoffice] 08/11: bank: fix URL, gnunet, 2021/12/20
- [taler-merchant-backoffice] 01/11: bank: implement login,
gnunet <=
- [taler-merchant-backoffice] 04/11: bank: fix URL generation, gnunet, 2021/12/20
- [taler-merchant-backoffice] 10/11: bank: implement withdrawal abort, gnunet, 2021/12/20
- [taler-merchant-backoffice] 02/11: Bank tests., gnunet, 2021/12/20
- [taler-merchant-backoffice] 11/11: bank: test withdrawal abort, gnunet, 2021/12/20
- [taler-merchant-backoffice] 09/11: bank: fix URL, gnunet, 2021/12/20
- [taler-merchant-backoffice] 06/11: remove misplaced comments, gnunet, 2021/12/20
- [taler-merchant-backoffice] 05/11: bank: make tests 'Content-Type' aware, gnunet, 2021/12/20
- [taler-merchant-backoffice] 07/11: bank: fix URL generation, gnunet, 2021/12/20