Skip to content

Commit

Permalink
feat(app): extend loading spinners until stamp verification is complete
Browse files Browse the repository at this point in the history
- loading spinners should be extended until stamp actually displays 'verified'
- changes passport operations (handleCreatePassport, handleAddStamp) to be async
- adds VerifyModal.test.tsx

[passportxyz#103]
  • Loading branch information
shavinac committed Jun 2, 2022
1 parent 70ffbe7 commit 10416ad
Show file tree
Hide file tree
Showing 17 changed files with 187 additions and 70 deletions.
6 changes: 4 additions & 2 deletions app/__tests__/components/ProviderCards/BrightidCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: "mockUserDid",
loggedIn: true,
Expand Down Expand Up @@ -151,7 +151,9 @@ describe("when the verify button is clicked", () => {
// Click the verify button on modal
fireEvent.click(finalVerifyButton!);

expect(handleAddStamp).toBeCalled();
await waitFor(() => {
expect(handleAddStamp).toBeCalled();
});
});

it("clicking cancel closes the modal and a stamp should not be added", async () => {
Expand Down
6 changes: 4 additions & 2 deletions app/__tests__/components/ProviderCards/EnsCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down Expand Up @@ -131,7 +131,9 @@ describe("when the verify button is clicked", () => {
// Click the verify button on modal
fireEvent.click(finalVerifyButton!);

expect(handleAddStamp).toBeCalled();
await waitFor(() => {
expect(handleAddStamp).toBeCalled();
});
});

it("clicking cancel closes the modal and a stamp should not be added", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down
2 changes: 1 addition & 1 deletion app/__tests__/components/ProviderCards/GoogleCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down
6 changes: 4 additions & 2 deletions app/__tests__/components/ProviderCards/PoapCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down Expand Up @@ -131,7 +131,9 @@ describe("when the verify button is clicked", () => {
// Click the verify button on modal
fireEvent.click(finalVerifyButton!);

expect(handleAddStamp).toBeCalled();
await waitFor(() => {
expect(handleAddStamp).toBeCalled();
});
});

it("clicking cancel closes the modal and a stamp should not be added", async () => {
Expand Down
12 changes: 5 additions & 7 deletions app/__tests__/components/ProviderCards/PohCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down Expand Up @@ -124,14 +124,12 @@ describe("when the verify button is clicked", () => {
expect(verifyModalButton).toBeInTheDocument();
});

const finalVerifyButton = screen.queryByRole("button", {
name: /Verify/,
});

// Click the verify button on modal
fireEvent.click(finalVerifyButton!);
fireEvent.click(screen.getByTestId("modal-verify"));

expect(handleAddStamp).toBeCalled();
await waitFor(() => {
expect(handleAddStamp).toBeCalled();
});
});

it("clicking cancel closes the modal and a stamp should not be added", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jest.mock("../../../utils/onboard.ts");

const mockHandleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const handleAddStamp = jest.fn();
const handleAddStamp = jest.fn().mockResolvedValue(undefined);
const mockUserContext: UserContextState = {
userDid: undefined,
loggedIn: true,
Expand Down
82 changes: 82 additions & 0 deletions app/__tests__/components/VerifyModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from "react";
import { render, screen } from "@testing-library/react";

import { VerifyModal, VerifyModalProps } from "../../components/VerifyModal";
import { ensStampFixture } from "../../__test-fixtures__/databaseStorageFixtures";

let props: VerifyModalProps;

beforeEach(() => {
props = {
isOpen: true,
onClose: jest.fn(),
handleUserVerify: jest.fn(),
stamp: ensStampFixture,
isLoading: false,
};
});

afterEach(() => {
jest.clearAllMocks();
});

describe("when stamp is not defined", () => {
beforeEach(() => {
props.stamp = undefined;
});

it("should not display your stamp credential", () => {
render(<VerifyModal {...props} />);
expect(screen.queryByText("Your Stamp Credential")).not.toBeInTheDocument();
});

it("does not show the buttons", () => {
render(<VerifyModal {...props} />);

expect(screen.queryByTestId("modal-verify")).not.toBeInTheDocument();
expect(screen.queryByTestId("modal-cancel")).not.toBeInTheDocument();
});
});

describe("when stamp is defined", () => {
it("displays the stamp credential", () => {
render(<VerifyModal {...props} />);

screen.getByText("Your Stamp Credential");
});

it("shows the buttons", () => {
render(<VerifyModal {...props} />);

screen.getByTestId("modal-verify");
screen.getByTestId("modal-cancel");
});
});

describe("when modal is loading", () => {
beforeEach(() => {
props.isLoading = true;
});

it("shows a loading spinner", () => {
render(<VerifyModal {...props} />);

screen.getByTestId("loading-spinner");
});
});

describe("buttons", () => {
it("includes a verify button that calls handleUserVerify", () => {
render(<VerifyModal {...props} />);

screen.getByTestId("modal-verify").click();
expect(props.handleUserVerify).toHaveBeenCalled();
});

it("includes a cancel button that calls onClose", () => {
render(<VerifyModal {...props} />);

screen.getByTestId("modal-cancel").click();
expect(props.onClose).toHaveBeenCalled();
});
});
16 changes: 12 additions & 4 deletions app/components/ProviderCards/BrightidCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default function BrightIdCard(): JSX.Element {
const [credentialResponseIsLoading, setCredentialResponseIsLoading] = useState(false);
const [brightIdVerification, SetBrightIdVerification] = useState<BrightIdProviderRecord | undefined>(undefined);
const toast = useToast();
const [verificationInProgress, setVerificationInProgress] = useState(false);

const handleFetchCredential = (): void => {
setCredentialResponseIsLoading(true);
Expand Down Expand Up @@ -114,9 +115,14 @@ export default function BrightIdCard(): JSX.Element {
}

const handleUserVerify = (): void => {
if (credentialResponse) {
handleAddStamp(credentialResponse);
}
handleAddStamp(credentialResponse!).finally(() => {
setVerificationInProgress(false);
});
onClose();
};

const handleModalOnClose = (): void => {
setVerificationInProgress(false);
onClose();
};

Expand Down Expand Up @@ -200,6 +206,7 @@ export default function BrightIdCard(): JSX.Element {
data-testid="button-verify-brightid"
className="verify-btn"
onClick={async () => {
setVerificationInProgress(true);
SetCredentialResponse(undefined);
SetBrightIdVerification(undefined);
const isVerified = await handleVerifyContextId();
Expand All @@ -213,7 +220,7 @@ export default function BrightIdCard(): JSX.Element {
</button>
<VerifyModal
isOpen={isOpen}
onClose={onClose}
onClose={handleModalOnClose}
stamp={credentialResponse}
handleUserVerify={handleUserVerify}
verifyData={
Expand All @@ -233,6 +240,7 @@ export default function BrightIdCard(): JSX.Element {
providerSpec={allProvidersState[providerId]!.providerSpec as ProviderSpec}
verifiableCredential={allProvidersState[providerId]!.stamp?.credential}
issueCredentialWidget={issueCredentialWidget}
isLoading={verificationInProgress}
/>
);
}
17 changes: 12 additions & 5 deletions app/components/ProviderCards/EnsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default function EnsCard(): JSX.Element {
const [credentialResponse, SetCredentialResponse] = useState<Stamp | undefined>(undefined);
const [credentialResponseIsLoading, setCredentialResponseIsLoading] = useState(false);
const [ens, SetEns] = useState<string | undefined>(undefined);
const [verificationInProgress, setVerificationInProgress] = useState(false);

const handleFetchCredential = (): void => {
setCredentialResponseIsLoading(true);
Expand Down Expand Up @@ -54,9 +55,14 @@ export default function EnsCard(): JSX.Element {
};

const handleUserVerify = (): void => {
if (credentialResponse) {
handleAddStamp(credentialResponse);
}
handleAddStamp(credentialResponse!).finally(() => {
setVerificationInProgress(false);
});
onClose();
};

const handleModalOnClose = (): void => {
setVerificationInProgress(false);
onClose();
};

Expand All @@ -66,6 +72,7 @@ export default function EnsCard(): JSX.Element {
data-testid="button-verify-ens"
className="verify-btn"
onClick={() => {
setVerificationInProgress(true);
SetCredentialResponse(undefined);
handleFetchCredential();
onOpen();
Expand All @@ -75,7 +82,7 @@ export default function EnsCard(): JSX.Element {
</button>
<VerifyModal
isOpen={isOpen}
onClose={onClose}
onClose={handleModalOnClose}
stamp={credentialResponse}
handleUserVerify={handleUserVerify}
verifyData={
Expand All @@ -95,7 +102,7 @@ export default function EnsCard(): JSX.Element {
providerSpec={allProvidersState[providerId]!.providerSpec as ProviderSpec}
verifiableCredential={allProvidersState[providerId]!.stamp?.credential}
issueCredentialWidget={issueCredentialWidget}
isLoading={credentialResponseIsLoading}
isLoading={verificationInProgress}
/>
);
}
8 changes: 5 additions & 3 deletions app/components/ProviderCards/FacebookCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,18 @@ export default function FacebookCard(): JSX.Element {
const [isLoading, setLoading] = useState(false);

const onClick = () => {
setLoading(true);
//@ts-ignore assuming FB.init was already called; see facebookSdkScript in pages/index.tsx
FB.login(function (response) {
if (response.status === "connected") {
onFacebookSignIn(response.authResponse);
} else {
setLoading(false);
}
});
};

const onFacebookSignIn = (response: ReactFacebookLoginInfo): void => {
setLoading(true);
// fetch the verifiable credential
fetchVerifiableCredential(
iamUrl,
Expand All @@ -64,8 +66,8 @@ export default function FacebookCard(): JSX.Element {
},
signer as { signMessage: (message: string) => Promise<string> }
)
.then((verified): void => {
handleAddStamp({
.then(async (verified): Promise<void> => {
await handleAddStamp({
provider: "Facebook",
credential: verified.credential,
});
Expand Down
23 changes: 15 additions & 8 deletions app/components/ProviderCards/GoogleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export default function GoogleCard(): JSX.Element {
const [isLoading, setLoading] = useState(false);

const onGoogleSignIn = (response: GoogleLoginResponse): void => {
setLoading(true);
// fetch the verifiable credential
fetchVerifiableCredential(
iamUrl,
Expand All @@ -41,8 +40,8 @@ export default function GoogleCard(): JSX.Element {
},
signer as { signMessage: (message: string) => Promise<string> }
)
.then((verified): void => {
handleAddStamp({
.then(async (verified): Promise<void> => {
await handleAddStamp({
provider: "Google",
credential: verified.credential,
});
Expand All @@ -55,6 +54,10 @@ export default function GoogleCard(): JSX.Element {
});
};

const onGoogleSignInFailure = (): void => {
setLoading(false);
};

return (
<Card
isLoading={isLoading}
Expand All @@ -63,14 +66,18 @@ export default function GoogleCard(): JSX.Element {
issueCredentialWidget={
<GoogleLogin
clientId={googleClientId}
onFailure={(response): void =>
// onGoogleSignIn(response as GoogleLoginResponse)
console.log("Google Login")
}
onFailure={onGoogleSignInFailure}
onSuccess={(response): void => onGoogleSignIn(response as GoogleLoginResponse)}
// To override all stylings...
render={(renderProps): JSX.Element => (
<button data-testid="button-verify-google" className="verify-btn" onClick={renderProps.onClick}>
<button
data-testid="button-verify-google"
className="verify-btn"
onClick={() => {
setLoading(true);
renderProps.onClick();
}}
>
Connect account
</button>
)}
Expand Down
Loading

0 comments on commit 10416ad

Please sign in to comment.