Skip to content

Commit

Permalink
UI redesign for 1 click to verify returning user (passportxyz#1097)
Browse files Browse the repository at this point in the history
* refactor(app): using standard grid layout

* small spacing updates. Using full header w/ warning banner, updated existing warnings to use this

* made loadingcard match platformcard

* moved top dashboard content into subheader

* standardized colors and fonts. Started landing page redesign

* feat(app): adds beginnings of new ui welcome back page + lint fixes

* feat(app): redesign for landing page (passportxyz#1078)

* refactor(app): control/define theme in JS (passportxyz#1081)

* feat(app): adds 1 click verification and ui redesign

* feat(app): adds navigation

* feat(app): adds error handling to fetch and bg

* fix(app): fix rebase issues

* feat(app): removes unnecessary imports & props, adds navigation

* feat(app): test refreshmystampmodal

* feat(app): test WelcomeBack

* feat(app): adds tests for welcome page and refresh card list

* feat(app): filters platform if user already has stamps

* feat(app): fixes duplicate stamp bug

* feat(app): fixes tests

---------

Co-authored-by: Lucian Hymer <[email protected]>
Co-authored-by: schultztimothy <[email protected]>
Co-authored-by: Chibuotu Amadi <[email protected]>
  • Loading branch information
4 people authored Apr 18, 2023
1 parent fda1c08 commit 683b5ad
Show file tree
Hide file tree
Showing 21 changed files with 1,218 additions and 3 deletions.
53 changes: 53 additions & 0 deletions app/__tests__/components/RefreshMyStampsModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { RefreshMyStampsModal, RefreshMyStampsModalProps } from "../../components/RefreshMyStampsModal";
import { PossibleEVMProvider } from "../../signer/utils";

const defaultProps: RefreshMyStampsModalProps = {
isOpen: true,
onClose: jest.fn(),
steps: [],
fetchedPossibleEVMStamps: undefined,
resetStampsAndProgressState: jest.fn(),
};

jest.mock("../../utils/onboard");

jest.mock("@didtools/cacao", () => ({
Cacao: {
fromBlockBytes: jest.fn(),
},
}));

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
useNavigate: () => jest.fn(),
}));

jest.mock("../../components/RefreshMyStampsModalContent.tsx", () => ({
RefreshMyStampsModalContent: () => <div data-testid="refresh-my-stamps-modal-content" />,
}));

jest.mock("../../components/RefreshStampsProgressSteps.tsx", () => ({
__esModule: true, // Required for default export mocking
default: () => <div data-testid="refresh-stamps-progress-steps" />,
}));

describe("RefreshMyStampsModal", () => {
it("renders the component with searching for stamps when fetchedPossibleEVMStamps is undefined", () => {
render(<RefreshMyStampsModal {...defaultProps} />);

expect(screen.getByText("Searching for Stamps")).toBeInTheDocument();
expect(screen.getByText("Give us a moment while we check your account for existing Stamps.")).toBeInTheDocument();
expect(screen.getByText("Please do not close the window.")).toBeInTheDocument();
});

it("renders the component with RefreshMyStampsModalContent when fetchedPossibleEVMStamps is not undefined", () => {
const fetchedPossibleEVMStamps = [{ provider: "ethereum", platform_id: "1" }] as unknown as PossibleEVMProvider[];
render(<RefreshMyStampsModal {...defaultProps} fetchedPossibleEVMStamps={fetchedPossibleEVMStamps} />);

expect(screen.getByTestId("refresh-my-stamps-modal-content")).toBeInTheDocument();
});
});
104 changes: 104 additions & 0 deletions app/__tests__/components/RefreshMyStampsModalContentCardList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from "react";
import { screen, render, waitFor } from "@testing-library/react";

import { UserContextState } from "../../context/userContext";
import {
RefreshMyStampsModalContentCardList,
RefreshMyStampsModalCardListProps,
} from "../../components/RefreshMyStampsModalContentCardList";
import {
RefreshMyStampsModalContent,
RefreshMyStampsModalContentProps,
} from "../../components/RefreshMyStampsModalContent";
import {
makeTestCeramicContext,
makeTestUserContext,
renderWithContext,
} from "../../__test-fixtures__/contextTestHelpers";
import { CeramicContextState } from "../../context/ceramicContext";
import { PossibleEVMProvider } from "../../signer/utils";

const defaultProps: RefreshMyStampsModalCardListProps = {
fetchedPossibleEVMStamps: undefined,
verifiedProviders: [],
selectedProviders: [],
selectedEVMPlatformProviders: [],
setSelectedProviders: jest.fn(),
setSelectedEVMPlatformProviders: jest.fn(),
};

const fetchedPossibleEVMStamps = [
{
platformProps: {
platform: {
path: "ethereum",
platform_id: "1",
},
},
},
] as unknown as PossibleEVMProvider[];

const RefreshMyStampsModalContentPropsList: RefreshMyStampsModalContentProps = {
resetStampsAndProgressState: jest.fn(),
onClose: jest.fn(),
fetchedPossibleEVMStamps: fetchedPossibleEVMStamps,
};

jest.mock("../../utils/onboard.ts");

jest.mock("@didtools/cacao", () => ({
Cacao: {
fromBlockBytes: jest.fn(),
},
}));

jest.mock("react-router-dom", () => ({
useNavigate: () => jest.fn(),
}));

jest.mock("../../components/RefreshMyStampsModalContentCard.tsx", () => ({
RefreshMyStampsModalContentCard: () => (
<div data-testid="refresh-my-stamps-modal-content-card">Mock refresh card</div>
),
}));

const mockUserContext: UserContextState = makeTestUserContext();
const mockCeramicContext: CeramicContextState = makeTestCeramicContext();

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

describe("RefreshMyStampsModalContentCardList", () => {
it("renders the component after fetched stamps have been found", async () => {
const refreshModal = () => {
return (
<RefreshMyStampsModalContent {...RefreshMyStampsModalContentPropsList}>
<RefreshMyStampsModalContentCardList {...defaultProps} />
</RefreshMyStampsModalContent>
);
};

renderWithContext(mockUserContext, mockCeramicContext, refreshModal());
await waitFor(() => expect(screen.getByTestId("refresh-my-stamps-modal-content-card")).toBeInTheDocument());
});

it("renders the component after fetched stamps have been found", async () => {
const RefreshMyStampsModalContentPropsList: RefreshMyStampsModalContentProps = {
resetStampsAndProgressState: jest.fn(),
onClose: jest.fn(),
fetchedPossibleEVMStamps: [],
};

const refreshModal = () => {
return (
<RefreshMyStampsModalContent {...RefreshMyStampsModalContentPropsList}>
<RefreshMyStampsModalContentCardList {...defaultProps} />
</RefreshMyStampsModalContent>
);
};

renderWithContext(mockUserContext, mockCeramicContext, refreshModal());
await waitFor(() => expect(screen.getByText("No Eligible Web3 Stamps Found")).toBeInTheDocument());
});
});
36 changes: 36 additions & 0 deletions app/__tests__/components/WelcomeBack.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { WelcomeBack, WelcomeBackProps } from "../../components/WelcomeBack";
import { useNavigate } from "react-router-dom";

const defaultProps: WelcomeBackProps = {
onOpen: jest.fn(),
handleFetchPossibleEVMStamps: jest.fn(),
resetStampsAndProgressState: jest.fn(),
};

jest.mock("../../utils/onboard");

jest.mock("@didtools/cacao", () => ({
Cacao: {
fromBlockBytes: jest.fn(),
},
}));

jest.mock("react-router-dom", () => ({
useNavigate: () => jest.fn(),
}));

describe("WelcomeBack", () => {
it("renders the component", () => {
render(<WelcomeBack {...defaultProps} />);

expect(screen.getByText("Welcome Back!")).toBeInTheDocument();
expect(screen.getByText("One-Click Verification")).toBeInTheDocument();
expect(
screen.getByText(
"You can now verify most web3 stamps and return to your destination faster with one-click verification!"
)
).toBeInTheDocument();
});
});
139 changes: 139 additions & 0 deletions app/__tests__/pages/Welcome.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import React from "react";
import { screen, waitFor, fireEvent, render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Welcome from "../../pages/Welcome";
import { UserContextState } from "../../context/userContext";
import { HashRouter as Router } from "react-router-dom";
import * as framework from "@self.id/framework";
import {
makeTestCeramicContext,
makeTestUserContext,
renderWithContext,
} from "../../__test-fixtures__/contextTestHelpers";
import { RefreshMyStampsModal } from "../../components/RefreshMyStampsModal";
import { CeramicContextState } from "../../context/ceramicContext";

jest.mock("../../utils/onboard.ts");

jest.mock("@didtools/cacao", () => ({
Cacao: {
fromBlockBytes: jest.fn(),
},
}));

jest.mock("@self.id/framework", () => {
return {
useViewerConnection: jest.fn(),
};
});

const mockUserContext: UserContextState = makeTestUserContext();
const mockCeramicContext: CeramicContextState = makeTestCeramicContext();

jest.mock("../../components/RefreshMyStampsModal.tsx", () => ({
RefreshMyStampsModal: () => <div data-testid="refresh-my-stamps-modal" />,
}));

beforeEach(() => {
jest.clearAllMocks();
(framework.useViewerConnection as jest.Mock).mockImplementation(() => [
{
status: "connected",
},
jest.fn(),
jest.fn(),
]);
});

describe("Welcome", () => {
it("renders the page", () => {
renderWithContext(
mockUserContext,
mockCeramicContext,
<Router>
<Welcome />
</Router>
);

expect(screen.getByText("Welcome Back!")).toBeInTheDocument();
expect(screen.getByText("One-Click Verification")).toBeInTheDocument();
expect(
screen.getByText(
"You can now verify most web3 stamps and return to your destination faster with one-click verification!"
)
).toBeInTheDocument();
});
});

describe("when the user is navigated to the Welcome page", () => {
it("should render the Skip for Now button", () => {
renderWithContext(
mockUserContext,
mockCeramicContext,
<Router>
<Welcome />
</Router>
);

expect(screen.getByTestId("skip-for-now-button"));
});

it("should render the Refresh My Stamps button", () => {
renderWithContext(
mockUserContext,
mockCeramicContext,
<Router>
<Welcome />
</Router>
);

expect(screen.getByTestId("refresh-my-stamps-button"));
});
});

// describe("when the user clicks the Skip for Now button", () => {
// it("should navigate to the Dashboard", async () => {
// const mockCeramicConnect = jest.fn();
// (framework.useViewerConnection as jest.Mock).mockReturnValue([{ status: "connected" }, mockCeramicConnect]);

// jest.mock("react-router-dom", () => ({
// useNavigate: () => jest.fn(),
// }));
// // renderWithContext(
// // mockUserContext,
// // mockCeramicContext,
// // <Router>
// // <Welcome />
// // </Router>
// // );

// render(<Welcome />);

// const buttonSkipForNow = screen.getByTestId("skip-for-now-button");

// fireEvent.click(buttonSkipForNow!);

// await waitFor(() => expect(window.));
// });
// });

describe("when the user clicks the Refresh My Stamps button it launches the Refresh My Stamps modal", () => {
it("should render the refresh stamps modal", () => {
renderWithContext(
mockUserContext,
mockCeramicContext,
<Router>
<Welcome />
</Router>
);

const buttonRefreshMyStampsModal = screen.queryByTestId("refresh-my-stamps-button");

fireEvent.click(buttonRefreshMyStampsModal!);

const refreshMyStampsModal = screen.getByTestId("refresh-my-stamps-modal");

expect(refreshMyStampsModal).toBeInTheDocument();
expect(screen.getByTestId("refresh-my-stamps-modal")).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion app/components/Progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export enum Status {

export type Step = {
name: string;
description: string;
description?: string;
status: Status;
};

Expand Down
Loading

0 comments on commit 683b5ad

Please sign in to comment.