Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/atoms/buttons/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ButtonStyles } from "../constants/button-styles";
import { ButtonTypes } from "../constants/button-types";
import React, { forwardRef } from "react";
import { StringUtils } from "andculturecode-javascript-core";
import { AccessibilityLabels } from "../../enums/accessibility-labels";

// -----------------------------------------------------------------------------------------
// #region Interfaces
Expand Down Expand Up @@ -84,7 +85,9 @@ const Button: React.RefForwardingComponent<
{children}
{accessibleText != null && (
// if
<span className="sr-only">{accessibleText}</span>
<span className={AccessibilityLabels.ScreenReadersOnlyClass}>
{accessibleText}
</span>
)}
</button>
);
Expand Down
3 changes: 3 additions & 0 deletions src/enums/accessibility-labels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum AccessibilityLabels {
ScreenReadersOnlyClass = "sr-only",
}
133 changes: 131 additions & 2 deletions src/molecules/form-fields/input-form-field.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";
import { render } from "@testing-library/react";
import { InputFormField } from "./input-form-field";
import { render, fireEvent } from "@testing-library/react";
import { InputFormField, InputFormFieldInvalidClass } from "./input-form-field";
import faker from "faker";
import { AccessibilityLabels } from "../../enums/accessibility-labels";

describe("InputFormField", () => {
test("when default props, renders input with label", () => {
Expand All @@ -16,4 +17,132 @@ describe("InputFormField", () => {
// Assert
expect(getByLabelText(expected)).not.toBeNull();
});

test("when errorsMessages prop set, renders with error messages", () => {
// Arrange
const errorMessages = [faker.random.words(), faker.random.words()];
const label = faker.random.words();

// Act
const { getByText } = render(
<InputFormField
errorMessages={errorMessages}
label={label}
onChange={() => {}}
/>
);

// Assert
expect(getByText(errorMessages[0])).not.toBeNil();
expect(getByText(errorMessages[1])).not.toBeNil();
});

test("when errorsMessage prop set, renders with error message", () => {
// Arrange
const label = faker.random.words();
const testErrorMessage = faker.random.words();

// Act
const { getByText } = render(
<InputFormField
errorMessage={testErrorMessage}
label={label}
onChange={() => {}}
/>
);

// Assert
expect(getByText(testErrorMessage)).not.toBeNil();
});

test(`when isValid prop set to false, renders with ${InputFormFieldInvalidClass} class name`, () => {
// Arrange
const label = faker.random.words();

// Act
const { container } = render(
<InputFormField isValid={false} label={label} onChange={() => {}} />
);
const result = container.getElementsByClassName(
InputFormFieldInvalidClass
);

// Assert
expect(result).toHaveLength(1);
});

test(`when isValid prop set to true, renders without ${InputFormFieldInvalidClass} class name`, () => {
// Arrange
const label = faker.random.words();

// Act
const { container } = render(
<InputFormField isValid={true} label={label} onChange={() => {}} />
);
const result = container.getElementsByClassName(
InputFormFieldInvalidClass
);

// Assert
expect(result).toHaveLength(0);
});

test("when required prop set, renders with required text", () => {
// Arrange
const label = faker.random.words();
const requiredText = "*";

// Act
const { container } = render(
<InputFormField label={label} onChange={() => {}} required={true} />
);
const htmlLabelTag = container.getElementsByTagName("label");

// Assert
expect(htmlLabelTag[0].textContent).toContain(requiredText);
});

test(`when showLabelForScreenReadersOnly prop set, renders with ${AccessibilityLabels.ScreenReadersOnlyClass} class name`, () => {
// Arrange
const label = faker.random.words();

// Act
const { container } = render(
<InputFormField
label={label}
onChange={() => {}}
showLabelForScreenReadersOnly={true}
/>
);
const htmlLabelTag = container.getElementsByTagName("span");

// Assert
expect(htmlLabelTag[0].classList).toContain(
AccessibilityLabels.ScreenReadersOnlyClass
);
});

test("when onChange set, calls handler upon change", () => {
// Arrange
let isChecked = false;
const label = faker.random.word();
const handleChange = () => (isChecked = true);
const inputTestId = "inputTestId";

// Act
const { getByTestId } = render(
<InputFormField
inputTestId={inputTestId}
label={label}
onChange={handleChange}
/>
);

fireEvent.change(getByTestId(inputTestId), {
target: { value: faker.random.word() },
});

// Assert
expect(isChecked).toBeTrue();
});
});
11 changes: 8 additions & 3 deletions src/molecules/form-fields/input-form-field.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { forwardRef, Ref, RefObject } from "react";
import uuid from "uuid";
import { AccessibilityLabels } from "../../enums/accessibility-labels";
import { CollectionUtils, StringUtils } from "andculturecode-javascript-core";
import { InputCharacterCount } from "../../atoms/forms/input-character-count";
import { InputTypes } from "../../atoms/constants/input-types";
Expand All @@ -10,6 +11,7 @@ import { InputProperties } from "../../atoms/interfaces/input-properties";
// -----------------------------------------------------------------------------------------

const COMPONENT_CLASS = "c-form-field";
export const InputFormFieldInvalidClass = "-invalid";

// #endregion Constants

Expand Down Expand Up @@ -64,14 +66,17 @@ const InputFormField: React.RefForwardingComponent<
value,
} = props;

const cssIsValid = isValid ? "" : "-invalid";
const cssIsValid = isValid ? "" : InputFormFieldInvalidClass;
const fieldId = props.fieldId ?? uuid.v4();

return (
<div className={`${COMPONENT_CLASS} ${cssIsValid}`}>
<label htmlFor={fieldId}>
{showLabelForScreenReadersOnly ? (
<span className="sr-only">{label}</span>
<span
className={AccessibilityLabels.ScreenReadersOnlyClass}>
{label}
</span>
) : (
<React.Fragment>{label}</React.Fragment>
)}
Expand All @@ -82,7 +87,7 @@ const InputFormField: React.RefForwardingComponent<
)}
</label>
<input
data-test-id={inputTestId}
data-testid={inputTestId}
disabled={disabled}
id={fieldId}
placeholder={placeholder}
Expand Down