Написал небольшую форму на Next.Js для того, чтобы протестировать её всеми способами. Я использовал scss modules в связке с Tailwindcss. Это выглядит примерно вот так:
import { InputHTMLAttributes, ReactHTMLElement } from "react";
import styles from "./input.module.scss";
import { FieldError } from "react-hook-form";
import clsx from "clsx";
interface Props extends InputHTMLAttributes<HTMLInputElement> {
label: string;
error?: FieldError;
validated?: boolean | undefined;
props?: ReactHTMLElement<HTMLInputElement>;
}
export default function Input(allProps: Props) {
const { label, error, validated, placeholder, ...props } = allProps;
return (
<div className={styles.container} data-testid={`Input: ${label}`}>
<input
className={clsx(
styles.input,
error !== undefined && styles.error,
validated === true && styles.success
)}
placeholder={error === undefined ? placeholder : error.message}
{...props}
data-testid={`Input-input: ${label}`}
/>
<h3
className={clsx(
styles.label,
error !== undefined && styles.error,
validated === true && styles.success
)}
data-testid={`Input-label: ${label}`}
>
{label}
</h3>
</div>
);
}
@reference '../../globals.css';
.container {
@apply relative w-full;
}
.input {
@apply w-full h-13 rounded-xl px-4 text-xl text-foreground/50 whitespace-nowrap text-ellipsis overflow-hidden;
outline: 1px solid rgba(var(--foreground-rgb), 0.5);
transition-duration: 200ms;
&:focus {
@apply outline-foreground text-foreground;
&::placeholder {
@apply text-transparent;
}
}
&::placeholder {
@apply text-2xl text-foreground/50 whitespace-nowrap text-ellipsis overflow-hidden;
}
}
.error {
@apply outline-red-600 text-red-600!;
&::placeholder {
@apply text-red-600/50;
}
&:focus {
@apply text-red-500 outline-red-500;
}
}
.success {
@apply outline-green-600 text-green-600!;
&::placeholder {
@apply text-green-600/50;
}
&:focus {
@apply text-green-500 outline-green-500;
}
}
.label {
@apply bg-background rounded-sm px-1 text-[14px] text-foreground absolute left-4 -top-5 opacity-0;
transition-duration: 200ms;
}
.input:focus + .label {
@apply opacity-100 -top-2.5;
}
Смесь @apply и обычных стилей связана с некоторыми проблемами, возникающими при билде некоторых tailwind классов. В любом случае, к вопросу это не относится, прошу не обращать внимание.
Проблема заключается в том, что, как вы видите, в классе .label прямо прописано opacity-0, однако в тесте проверка на видимость и на свойство opacity возвращает ошибку. Тесты:
test("Input: focus", async () => {
const input = render(<Input label="Test" placeholder="Test placeholder" />);
const label = input.getByTestId(`Input-label: Test`);
expect(label).toHaveStyle("opacity: 0");
});
test("Input: focus", async () => {
const input = render(<Input label="Test" placeholder="Test placeholder" />);
const label = input.getByTestId(`Input-label: Test`);
expect(label).toBeVisible();
});
В обоих случаях тесты не проходят. Я пытался использовать transfer библиотеки jest-css-modules-transform, jest-scss-transform, jest-transform-scss. Да, последние 2 это разные библиотеки.
Ссылка на репозиторий, однако тестов там нет, так как не получилось их сделать.