feat(e2e): add data-testids to components

This commit is contained in:
QAComet 2024-04-21 17:15:27 -06:00
parent 389db59b28
commit cd09843b99
7 changed files with 59 additions and 11 deletions

View File

@ -4,6 +4,7 @@ type Props = {
loading?: boolean; loading?: boolean;
className?: string; className?: string;
type?: "button" | "submit" | "reset" | undefined; type?: "button" | "submit" | "reset" | undefined;
"data-testid"?: string;
}; };
export default function AccentSubmitButton({ export default function AccentSubmitButton({
@ -12,6 +13,7 @@ export default function AccentSubmitButton({
loading, loading,
className, className,
type, type,
"data-testid": dataTestId,
}: Props) { }: Props) {
return ( return (
<button <button
@ -19,6 +21,7 @@ export default function AccentSubmitButton({
className={`border primary-btn-gradient select-none duration-200 bg-black border-[oklch(var(--p))] hover:border-[#0070b5] rounded-lg text-center px-4 py-2 text-white active:scale-95 tracking-wider w-fit flex justify-center items-center gap-2 ${ className={`border primary-btn-gradient select-none duration-200 bg-black border-[oklch(var(--p))] hover:border-[#0070b5] rounded-lg text-center px-4 py-2 text-white active:scale-95 tracking-wider w-fit flex justify-center items-center gap-2 ${
className || "" className || ""
}`} }`}
data-testid={dataTestId}
onClick={() => { onClick={() => {
if (loading !== undefined && !loading && onClick) onClick(); if (loading !== undefined && !loading && onClick) onClick();
}} }}

View File

@ -32,8 +32,14 @@ export default function Modal({ toggleModal, className, children }: Props) {
<Drawer.Overlay className="fixed inset-0 bg-black/40" /> <Drawer.Overlay className="fixed inset-0 bg-black/40" />
<ClickAwayHandler onClickOutside={() => setDrawerIsOpen(false)}> <ClickAwayHandler onClickOutside={() => setDrawerIsOpen(false)}>
<Drawer.Content className="flex flex-col rounded-t-2xl h-[90%] mt-24 fixed bottom-0 left-0 right-0 z-30"> <Drawer.Content className="flex flex-col rounded-t-2xl h-[90%] mt-24 fixed bottom-0 left-0 right-0 z-30">
<div className="p-4 pb-32 bg-base-100 rounded-t-2xl flex-1 border-neutral-content border-t overflow-y-auto"> <div
<div className="mx-auto w-12 h-1.5 flex-shrink-0 rounded-full bg-neutral mb-5" /> className="p-4 pb-32 bg-base-100 rounded-t-2xl flex-1 border-neutral-content border-t overflow-y-auto"
data-testid="mobile-modal-container"
>
<div
className="mx-auto w-12 h-1.5 flex-shrink-0 rounded-full bg-neutral mb-5"
data-testid="mobile-modal-slider"
/>
{children} {children}
</div> </div>
@ -44,19 +50,28 @@ export default function Modal({ toggleModal, className, children }: Props) {
); );
} else { } else {
return ( return (
<div className="overflow-y-auto pt-2 sm:py-2 fixed top-0 bottom-0 right-0 left-0 bg-black bg-opacity-10 backdrop-blur-sm flex justify-center items-center fade-in z-40"> <div
className="overflow-y-auto pt-2 sm:py-2 fixed top-0 bottom-0 right-0 left-0 bg-black bg-opacity-10 backdrop-blur-sm flex justify-center items-center fade-in z-40"
data-testid="modal-outer"
>
<ClickAwayHandler <ClickAwayHandler
onClickOutside={toggleModal} onClickOutside={toggleModal}
className={`w-full mt-auto sm:m-auto sm:w-11/12 sm:max-w-2xl ${ className={`w-full mt-auto sm:m-auto sm:w-11/12 sm:max-w-2xl ${
className || "" className || ""
}`} }`}
> >
<div className="slide-up mt-auto sm:m-auto relative border-neutral-content rounded-t-2xl sm:rounded-2xl border-t sm:border shadow-2xl p-5 bg-base-100 overflow-y-auto sm:overflow-y-visible"> <div
className="slide-up mt-auto sm:m-auto relative border-neutral-content rounded-t-2xl sm:rounded-2xl border-t sm:border shadow-2xl p-5 bg-base-100 overflow-y-auto sm:overflow-y-visible"
data-testid="modal-container"
>
<div <div
onClick={toggleModal as MouseEventHandler<HTMLDivElement>} onClick={toggleModal as MouseEventHandler<HTMLDivElement>}
className="absolute top-4 right-3 btn btn-sm outline-none btn-circle btn-ghost z-10" className="absolute top-4 right-3 btn btn-sm outline-none btn-circle btn-ghost z-10"
> >
<i className="bi-x text-neutral text-2xl"></i> <i
className="bi-x text-neutral text-2xl"
data-testid="close-modal-button"
></i>
</div> </div>
{children} {children}
</div> </div>

View File

@ -9,6 +9,7 @@ type Props = {
onKeyDown?: KeyboardEventHandler<HTMLInputElement> | undefined; onKeyDown?: KeyboardEventHandler<HTMLInputElement> | undefined;
className?: string; className?: string;
spellCheck?: boolean; spellCheck?: boolean;
"data-testid"?: string;
}; };
export default function TextInput({ export default function TextInput({
@ -20,9 +21,11 @@ export default function TextInput({
onKeyDown, onKeyDown,
className, className,
spellCheck, spellCheck,
"data-testid": dataTestId,
}: Props) { }: Props) {
return ( return (
<input <input
data-testid={dataTestId}
spellCheck={spellCheck} spellCheck={spellCheck}
autoFocus={autoFocus} autoFocus={autoFocus}
type={type ? type : "text"} type={type ? type : "text"}

View File

@ -6,13 +6,21 @@ import React, { ReactNode, useEffect } from "react";
interface Props { interface Props {
text?: string; text?: string;
children: ReactNode; children: ReactNode;
"data-testid"?: string;
} }
export default function CenteredForm({ text, children }: Props) { export default function CenteredForm({
text,
children,
"data-testid": dataTestId,
}: Props) {
const { settings } = useLocalSettingsStore(); const { settings } = useLocalSettingsStore();
return ( return (
<div className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center p-5"> <div
className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center p-5"
data-testid={dataTestId}
>
<div className="m-auto flex flex-col gap-2 w-full"> <div className="m-auto flex flex-col gap-2 w-full">
{settings.theme ? ( {settings.theme ? (
<Image <Image

View File

@ -38,7 +38,7 @@ export default function MainLayout({ children }: Props) {
<AnnouncementBar toggleAnnouncementBar={toggleAnnouncementBar} /> <AnnouncementBar toggleAnnouncementBar={toggleAnnouncementBar} />
) : undefined} ) : undefined}
<div className="flex"> <div className="flex" data-testid="dashboard-wrapper">
<div className="hidden lg:block"> <div className="hidden lg:block">
<Sidebar <Sidebar
className={`fixed ${showAnnouncement ? "top-10" : "top-0"}`} className={`fixed ${showAnnouncement ? "top-10" : "top-0"}`}

View File

@ -69,7 +69,7 @@ export default function Login({
function displayLoginCredential() { function displayLoginCredential() {
if (availableLogins.credentialsEnabled === "true") { if (availableLogins.credentialsEnabled === "true") {
return ( return (
<> <div data-testid="login-form">
<p className="text-3xl text-black dark:text-white text-center font-extralight"> <p className="text-3xl text-black dark:text-white text-center font-extralight">
Enter your credentials Enter your credentials
</p> </p>
@ -87,6 +87,7 @@ export default function Login({
placeholder="johnny" placeholder="johnny"
value={form.username} value={form.username}
className="bg-base-100" className="bg-base-100"
data-testid="username-input"
onChange={(e) => setForm({ ...form, username: e.target.value })} onChange={(e) => setForm({ ...form, username: e.target.value })}
/> />
</div> </div>
@ -100,6 +101,7 @@ export default function Login({
placeholder="••••••••••••••" placeholder="••••••••••••••"
value={form.password} value={form.password}
className="bg-base-100" className="bg-base-100"
data-testid="password-input"
onChange={(e) => setForm({ ...form, password: e.target.value })} onChange={(e) => setForm({ ...form, password: e.target.value })}
/> />
{availableLogins.emailEnabled === "true" && ( {availableLogins.emailEnabled === "true" && (
@ -107,6 +109,7 @@ export default function Login({
<Link <Link
href={"/forgot"} href={"/forgot"}
className="text-gray-500 dark:text-gray-400 font-semibold" className="text-gray-500 dark:text-gray-400 font-semibold"
data-testid="forgot-password-link"
> >
Forgot Password? Forgot Password?
</Link> </Link>
@ -117,13 +120,14 @@ export default function Login({
type="submit" type="submit"
label="Login" label="Login"
className=" w-full text-center" className=" w-full text-center"
data-testid="submit-login-button"
loading={submitLoader} loading={submitLoader}
/> />
{availableLogins.buttonAuths.length > 0 ? ( {availableLogins.buttonAuths.length > 0 ? (
<div className="divider my-1">OR</div> <div className="divider my-1">OR</div>
) : undefined} ) : undefined}
</> </div>
); );
} }
} }
@ -155,6 +159,7 @@ export default function Login({
<Link <Link
href={"/register"} href={"/register"}
className="block text-black dark:text-white font-semibold" className="block text-black dark:text-white font-semibold"
data-testid="register-link"
> >
Sign Up Sign Up
</Link> </Link>

View File

@ -102,6 +102,7 @@ export default function Register() {
} days of Premium Service at no cost!` } days of Premium Service at no cost!`
: "Create a new account" : "Create a new account"
} }
data-testid="registration-form"
> >
{process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" ? ( {process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" ? (
<div className="p-4 flex flex-col gap-3 justify-between max-w-[30rem] min-w-80 w-full bg-base-200 rounded-2xl shadow-md border border-neutral-content"> <div className="p-4 flex flex-col gap-3 justify-between max-w-[30rem] min-w-80 w-full bg-base-200 rounded-2xl shadow-md border border-neutral-content">
@ -127,6 +128,7 @@ export default function Register() {
placeholder="Johnny" placeholder="Johnny"
value={form.name} value={form.name}
className="bg-base-100" className="bg-base-100"
data-testid="display-name-input"
onChange={(e) => setForm({ ...form, name: e.target.value })} onChange={(e) => setForm({ ...form, name: e.target.value })}
/> />
</div> </div>
@ -139,6 +141,7 @@ export default function Register() {
placeholder="john" placeholder="john"
value={form.username} value={form.username}
className="bg-base-100" className="bg-base-100"
data-testid="username-input"
onChange={(e) => onChange={(e) =>
setForm({ ...form, username: e.target.value }) setForm({ ...form, username: e.target.value })
} }
@ -155,6 +158,7 @@ export default function Register() {
placeholder="johnny@example.com" placeholder="johnny@example.com"
value={form.email} value={form.email}
className="bg-base-100" className="bg-base-100"
data-testid="email-input"
onChange={(e) => setForm({ ...form, email: e.target.value })} onChange={(e) => setForm({ ...form, email: e.target.value })}
/> />
</div> </div>
@ -168,6 +172,7 @@ export default function Register() {
placeholder="••••••••••••••" placeholder="••••••••••••••"
value={form.password} value={form.password}
className="bg-base-100" className="bg-base-100"
data-testid="password-input"
onChange={(e) => setForm({ ...form, password: e.target.value })} onChange={(e) => setForm({ ...form, password: e.target.value })}
/> />
</div> </div>
@ -182,6 +187,7 @@ export default function Register() {
placeholder="••••••••••••••" placeholder="••••••••••••••"
value={form.passwordConfirmation} value={form.passwordConfirmation}
className="bg-base-100" className="bg-base-100"
data-testid="password-confirm-input"
onChange={(e) => onChange={(e) =>
setForm({ ...form, passwordConfirmation: e.target.value }) setForm({ ...form, passwordConfirmation: e.target.value })
} }
@ -195,6 +201,7 @@ export default function Register() {
<Link <Link
href="https://linkwarden.app/tos" href="https://linkwarden.app/tos"
className="font-semibold underline" className="font-semibold underline"
data-testid="terms-of-service-link"
> >
Terms of Service Terms of Service
</Link>{" "} </Link>{" "}
@ -202,6 +209,7 @@ export default function Register() {
<Link <Link
href="https://linkwarden.app/privacy-policy" href="https://linkwarden.app/privacy-policy"
className="font-semibold underline" className="font-semibold underline"
data-testid="privacy-policy-link"
> >
Privacy Policy Privacy Policy
</Link> </Link>
@ -212,6 +220,7 @@ export default function Register() {
<Link <Link
href="mailto:support@linkwarden.app" href="mailto:support@linkwarden.app"
className="font-semibold underline" className="font-semibold underline"
data-testid="support-link"
> >
Get in touch Get in touch
</Link> </Link>
@ -225,10 +234,15 @@ export default function Register() {
label="Sign Up" label="Sign Up"
className="w-full" className="w-full"
loading={submitLoader} loading={submitLoader}
data-testid="register-button"
/> />
<div className="flex items-baseline gap-1 justify-center"> <div className="flex items-baseline gap-1 justify-center">
<p className="w-fit text-neutral">Already have an account?</p> <p className="w-fit text-neutral">Already have an account?</p>
<Link href={"/login"} className="block font-bold"> <Link
href={"/login"}
className="block font-bold"
data-testid="login-link"
>
Login Login
</Link> </Link>
</div> </div>