Skip to content

Commit

Permalink
Show error toast if server side error
Browse files Browse the repository at this point in the history
  • Loading branch information
jamdelion committed Aug 29, 2024
1 parent 91f6de5 commit e7007a1
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import { optimisticallyUpdateMembersTable } from "./lib/optimisticallyUpdateMemb
export const AddNewEditorModal = ({
showModal,
setShowModal,
setShowToast,
setShowSuccessToast,
setShowErrorToast,
}: AddNewEditorModalProps) => {
const [showUserAlreadyExistsError, setShowUserAlreadyExistsError] =
useState<boolean>(false);

const clearErrors = () => {
setShowUserAlreadyExistsError(false);
setShowErrorToast(false);
};

const handleSubmit = async (
Expand All @@ -39,7 +41,7 @@ export const AddNewEditorModal = ({
) => {
const { teamId, teamSlug } = useStore.getState();

const newUserId = await createAndAddUserToTeam(
const createUserResult = await createAndAddUserToTeam(
values.email,
values.firstName,
values.lastName,
Expand All @@ -49,16 +51,19 @@ export const AddNewEditorModal = ({
if (isUserAlreadyExistsError(err.message)) {
setShowUserAlreadyExistsError(true);
}
if (err.message === "Unable to create user") {
setShowErrorToast(true);
}
console.error(err);
});

if (!newUserId) {
if (!createUserResult) {
return;
}
clearErrors();
optimisticallyUpdateMembersTable(values, newUserId);
optimisticallyUpdateMembersTable(values, createUserResult.id);
setShowModal(false);
setShowToast(true);
setShowSuccessToast(true);
resetForm({ values });
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,29 @@ export const MembersTable = ({
showAddMemberButton,
}: MembersTableProps) => {
const [showModal, setShowModal] = useState(false);
const [showToast, setShowToast] = useState(false);
const [showSuccessToast, setShowSuccessToast] = useState(false);
const [showErrorToast, setShowErrorToast] = useState(false);

const handleCloseToast = (
const handleCloseSuccessToast = (
_event?: React.SyntheticEvent | Event,
reason?: string,
) => {
if (reason === "clickaway") {
return;
}

setShowToast(false);
setShowSuccessToast(false);
};

const handleCloseErrorToast = (
_event?: React.SyntheticEvent | Event,
reason?: string,
) => {
if (reason === "clickaway") {
return;
}

setShowErrorToast(false);
};

const roleLabels: Record<string, string> = {
Expand Down Expand Up @@ -114,23 +126,39 @@ export const MembersTable = ({
</Table>
{showAddMemberButton && (
<Snackbar
open={showToast}
open={showSuccessToast}
autoHideDuration={6000}
onClose={handleCloseToast}
onClose={handleCloseSuccessToast}
>
<Alert
onClose={handleCloseToast}
onClose={handleCloseSuccessToast}
severity="success"
sx={{ width: "100%" }}
>
Successfully added a user
</Alert>
</Snackbar>
)}
{showAddMemberButton && (
<Snackbar
open={showErrorToast}
autoHideDuration={6000}
onClose={handleCloseErrorToast}
>
<Alert
onClose={handleCloseErrorToast}
severity="error"
sx={{ width: "100%" }}
>
Failed to add new user, please try again
</Alert>
</Snackbar>
)}
</TableContainer>
{showModal && (
<AddNewEditorModal
setShowToast={setShowToast}
setShowSuccessToast={setShowSuccessToast}
setShowErrorToast={setShowErrorToast}
showModal={showModal}
setShowModal={setShowModal}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { gql } from "@apollo/client";
import { FetchResult, gql } from "@apollo/client";
import { GET_USERS_FOR_TEAM_QUERY } from "routes/teamMembers";

import { client } from "../../../../../lib/graphql";

type CreateAndAddUserResponse = FetchResult<{
insert_users_one: { id: number; __typename: "users" };
}>;

export const createAndAddUserToTeam = async (
email: string,
firstName: string,
Expand All @@ -11,7 +15,7 @@ export const createAndAddUserToTeam = async (
teamSlug: string,
) => {
// NB: the user is hard-coded with the 'teamEditor' role for now
const response = (await client.mutate({
const response: CreateAndAddUserResponse = await client.mutate({
mutation: gql`
mutation CreateAndAddUserToTeam(
$email: String!
Expand Down Expand Up @@ -40,6 +44,9 @@ export const createAndAddUserToTeam = async (
refetchQueries: [
{ query: GET_USERS_FOR_TEAM_QUERY, variables: { teamSlug } },
],
})) as any;
return response.data.insert_users_one;
});
if (response.data) {
return response.data.insert_users_one;
}
throw new Error("Unable to create user");
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { screen } from "@testing-library/react";
import { FullStore, useStore } from "pages/FlowEditor/lib/store";
import { vi } from "vitest";

import { setupTeamMembersScreen } from "./helpers/setupTeamMembersScreen";
import { userTriesToAddNewEditor } from "./helpers/userTriesToAddNewEditor";
import { mockTeamMembersData } from "./mocks/mockTeamMembersData";
import { alreadyExistingUser } from "./mocks/mockUsers";

let initialState: FullStore;
vi.mock(
"pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx",
() => ({
createAndAddUserToTeam: vi.fn().mockRejectedValue({
message: "Unable to create user",
}),
}),
);

describe("when a user fills in the 'add a new editor' form correctly but there is a server-side error", () => {
afterAll(() => useStore.setState(initialState));
beforeEach(async () => {
useStore.setState({
teamMembers: [...mockTeamMembersData, alreadyExistingUser],
});

const { user } = await setupTeamMembersScreen();
await userTriesToAddNewEditor(user);
});

it("shows an appropriate error message", async () => {
expect(
await screen.findByText(/Failed to add new user, please try again/),
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ vi.mock(
}),
}),
);

let initialState: FullStore;

describe("when a user fills in the 'add a new editor' form correctly but the user already exists", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe("when the addNewEditor modal is rendered", () => {
<AddNewEditorModal
showModal={true}
setShowModal={() => {}}
setShowToast={() => {}}
setShowSuccessToast={() => {}}
/>
</DndProvider>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export interface MembersTableProps {
export interface AddNewEditorModalProps {
showModal: boolean;
setShowModal: React.Dispatch<SetStateAction<boolean>>;
setShowToast: React.Dispatch<SetStateAction<boolean>>;
setShowSuccessToast: React.Dispatch<SetStateAction<boolean>>;
setShowErrorToast: React.Dispatch<SetStateAction<boolean>>;
}

export interface AddNewEditorFormValues {
Expand Down

0 comments on commit e7007a1

Please sign in to comment.