add error message when setup fails on registration page (#7395)

* add error message when setup fails on registration page

* add test for error

Co-authored-by: Luke Heath <luke@fleetdm.com>
This commit is contained in:
Gabriel Hernandez 2022-08-31 17:17:27 +01:00 committed by GitHub
parent 2f10e53082
commit 8c017c3ef0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 38 deletions

View File

@ -0,0 +1 @@
* adds better messaging where there is an error in the setup flow

View File

@ -2,12 +2,40 @@ import CONSTANTS from "../../../support/constants";
const { GOOD_PASSWORD } = CONSTANTS;
const fillOutForm = () => {
// Page 1
cy.findByPlaceholderText(/full name/i).type("Test name");
cy.findByPlaceholderText(/email/i).type("test@example.com");
cy.findByPlaceholderText(/^password/i)
.first()
.type(GOOD_PASSWORD);
cy.findByPlaceholderText(/confirm password/i)
.last()
.type(GOOD_PASSWORD);
cy.contains("button:enabled", /next/i).click();
// Page 2
cy.findByPlaceholderText(/organization name/i).type("Fleet Test");
cy.contains("button:enabled", /next/i).click();
// Page 3
cy.contains("button:enabled", /next/i).click();
// Page 4
cy.contains("button:enabled", /confirm/i).click();
};
describe("Setup", () => {
// Different than normal beforeEach because we don't run the fleetctl setup.
beforeEach(() => {
const SHELL = Cypress.platform === "win32" ? "cmd" : "bash";
cy.exec("make e2e-reset-db", {
timeout: 5000,
timeout: 20000,
env: { SHELL },
});
});
@ -17,33 +45,20 @@ describe("Setup", () => {
cy.url().should("match", /\/setup$/);
cy.contains(/setup/i);
// Page 1
cy.findByPlaceholderText(/full name/i).type("Test name");
cy.findByPlaceholderText(/email/i).type("test@example.com");
cy.findByPlaceholderText(/^password/i)
.first()
.type(GOOD_PASSWORD);
cy.findByPlaceholderText(/confirm password/i)
.last()
.type(GOOD_PASSWORD);
cy.contains("button:enabled", /next/i).click();
// Page 2
cy.findByPlaceholderText(/organization name/i).type("Fleet Test");
cy.contains("button:enabled", /next/i).click();
// Page 3
cy.contains("button:enabled", /next/i).click();
// Page 4
cy.contains("button:enabled", /confirm/i).click();
fillOutForm();
cy.url().should("match", /\/hosts\/manage$/i);
cy.contains(/all hosts/i);
});
it("shows messaging when there is an error during setup", () => {
cy.visit("/");
cy.intercept("POST", "/api/v1/setup", { forceNetworkError: true });
fillOutForm();
cy.findByText(
"We were unable to configure Fleet. If your Fleet server is behind a proxy, please ensure the server can be reached."
).should("exist");
});
});

View File

@ -16,6 +16,7 @@ export interface IFlashMessage {
fullWidth: boolean;
notification: INotification | null;
isPersistent?: boolean;
className?: string;
onRemoveFlash: () => void;
onUndoActionClick?: (
value: () => void
@ -26,13 +27,19 @@ const FlashMessage = ({
fullWidth,
notification,
isPersistent,
className,
onRemoveFlash,
onUndoActionClick,
}: IFlashMessage): JSX.Element | null => {
const { alertType, isVisible, message, undoAction } = notification || {};
const klass = classnames(baseClass, `${baseClass}--${alertType}`, {
[`${baseClass}--full-width`]: fullWidth,
});
const baseClasses = classnames(
baseClass,
className,
`${baseClass}--${alertType}`,
{
[`${baseClass}--full-width`]: fullWidth,
}
);
const [hide, setHide] = useState(false);
@ -62,7 +69,7 @@ const FlashMessage = ({
}
return (
<div className={klass} id={klass}>
<div className={baseClasses} id={baseClasses}>
<div className={`${baseClass}__content`}>
{alertType === "success" ? (
<FleetIcon name="success-check" />

View File

@ -7,6 +7,8 @@ import { AppContext } from "context/app";
import usersAPI from "services/entities/users";
import local from "utilities/local";
import FlashMessage from "components/FlashMessage";
import { INotification } from "interfaces/notification";
// @ts-ignore
import RegistrationForm from "components/forms/RegistrationForm";
// @ts-ignore
@ -14,16 +16,26 @@ import Breadcrumbs from "./Breadcrumbs";
// @ts-ignore
import fleetLogoText from "../../../assets/images/fleet-logo-text-white.svg";
const ERROR_NOTIFICATION: INotification = {
alertType: "error",
isVisible: true,
message:
"We were unable to configure Fleet. If your Fleet server is behind a proxy, please ensure the server can be reached.",
};
interface IRegistrationPageProps {
router: InjectedRouter;
}
const baseClass = "registration-page";
const RegistrationPage = ({ router }: IRegistrationPageProps) => {
const { currentUser, setCurrentUser, setAvailableTeams } = useContext(
AppContext
);
const [page, setPage] = useState<number>(1);
const [pageProgress, setPageProgress] = useState<number>(1);
const [page, setPage] = useState(1);
const [pageProgress, setPageProgress] = useState(1);
const [showSetupError, setShowSetupError] = useState(false);
useEffect(() => {
const { HOME } = paths;
@ -51,10 +63,9 @@ const RegistrationPage = ({ router }: IRegistrationPageProps) => {
setAvailableTeams(available_teams);
return router.push(MANAGE_HOSTS);
} catch (error) {
// TODO: Alert user to server errors
console.log(error);
setPage(1);
return false;
setPageProgress(1);
setShowSetupError(true);
}
};
@ -67,11 +78,11 @@ const RegistrationPage = ({ router }: IRegistrationPageProps) => {
};
return (
<div className="registration-page">
<div className={baseClass}>
<img
alt="Fleet logo"
src={fleetLogoText}
className="registration-page__logo"
className={`${baseClass}__logo`}
/>
<Breadcrumbs
onClick={onSetPage}
@ -83,6 +94,14 @@ const RegistrationPage = ({ router }: IRegistrationPageProps) => {
onNextPage={onNextPage}
onSubmit={onRegistrationFormSubmit}
/>
{showSetupError && (
<FlashMessage
className={`${baseClass}__flash-message`}
fullWidth={false}
notification={ERROR_NOTIFICATION}
onRemoveFlash={() => setShowSetupError(false)}
/>
)}
</div>
);
};

View File

@ -8,7 +8,7 @@
&__logo {
@include position(absolute, 24px null null 24px);
width: 120px;
width: 20px;
@include breakpoint(tablet) {
width: 125px;
@ -17,4 +17,8 @@
margin: 15px 0 0 15px;
}
}
&__flash-message {
top: 180px;
}
}