Skip to content

Commit 1261a08

Browse files
author
Said Shah
committed
Merge branch 'main' of github.com:AndcultureCode/AndcultureCode.JavaScript.React.Components into main
2 parents 980ebce + 82b41b8 commit 1261a08

File tree

5 files changed

+226
-10
lines changed

5 files changed

+226
-10
lines changed

src/atoms/buttons/button.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ButtonStyles } from "../constants/button-styles";
33
import { ButtonTypes } from "../constants/button-types";
44
import React, { forwardRef } from "react";
55
import { StringUtils } from "andculturecode-javascript-core";
6+
import { AccessibilityLabels } from "../../enums/accessibility-labels";
67

78
// -----------------------------------------------------------------------------------------
89
// #region Interfaces
@@ -84,7 +85,9 @@ const Button: React.RefForwardingComponent<
8485
{children}
8586
{accessibleText != null && (
8687
// if
87-
<span className="sr-only">{accessibleText}</span>
88+
<span className={AccessibilityLabels.ScreenReadersOnlyClass}>
89+
{accessibleText}
90+
</span>
8891
)}
8992
</button>
9093
);

src/enums/accessibility-labels.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export enum AccessibilityLabels {
2+
ScreenReadersOnlyClass = "sr-only",
3+
}
Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,83 @@
1-
// import React from "react";
2-
// import { render } from "@testing-library/react";
3-
// import { DropdownButton } from "./dropdown-button";
1+
import React from "react";
2+
import faker from "faker";
3+
import { ButtonSizes } from "../../atoms/constants/button-sizes";
4+
import { ButtonStyles } from "../../atoms/constants/button-styles";
5+
import { DropdownButton } from "./dropdown-button";
6+
import { render } from "@testing-library/react";
47

58
describe("DropdownButton", () => {
6-
test.skip("TODO - https://github.com/AndcultureCode/AndcultureCode.JavaScript.React.Components/issues/21", () => {});
9+
const menuItems = [
10+
{ component: faker.random.word(), onSelect: () => {} },
11+
{ component: faker.random.word(), onSelect: () => {} },
12+
];
13+
14+
test("when default props, renders Dropdown Button", () => {
15+
// Arrange
16+
const expected = faker.random.words();
17+
18+
// Act
19+
const { getByText } = render(
20+
<DropdownButton buttonContents={expected} menuItems={menuItems} />
21+
);
22+
23+
// Assert
24+
expect(getByText(expected)).not.toBeNil();
25+
});
26+
27+
test("when buttonClassName prop provided, renders with class name", () => {
28+
// Arrange
29+
const testButtonContents = faker.random.words();
30+
const testButtonClassName = "testButtonClassName";
31+
32+
// Act
33+
const { container } = render(
34+
<DropdownButton
35+
buttonClassName={testButtonClassName}
36+
buttonContents={testButtonContents}
37+
menuItems={menuItems}
38+
/>
39+
);
40+
const result = container.getElementsByClassName(testButtonClassName);
41+
42+
// Assert
43+
expect(result).toHaveLength(1);
44+
});
45+
46+
test("when button size prop provided, renders with correct size class", () => {
47+
// Arrange
48+
const testButtonContents = faker.random.words();
49+
const testButtonSize = ButtonSizes.Large;
50+
51+
// Act
52+
const { container } = render(
53+
<DropdownButton
54+
buttonContents={testButtonContents}
55+
menuItems={menuItems}
56+
size={testButtonSize}
57+
/>
58+
);
59+
const result = container.getElementsByClassName(testButtonSize);
60+
61+
// Assert
62+
expect(result).toHaveLength(1);
63+
});
64+
65+
test("when button style prop provided, renders with correct style class", () => {
66+
// Arrange
67+
const testButtonContents = faker.random.words();
68+
const testButtonStyle = ButtonStyles.Destructive;
69+
70+
// Act
71+
const { container } = render(
72+
<DropdownButton
73+
buttonContents={testButtonContents}
74+
menuItems={menuItems}
75+
style={testButtonStyle}
76+
/>
77+
);
78+
const result = container.getElementsByClassName(testButtonStyle);
79+
80+
// Assert
81+
expect(result).toHaveLength(1);
82+
});
783
});

src/molecules/form-fields/input-form-field.test.tsx

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from "react";
2-
import { render } from "@testing-library/react";
3-
import { InputFormField } from "./input-form-field";
2+
import { render, fireEvent } from "@testing-library/react";
3+
import { InputFormField, InputFormFieldInvalidClass } from "./input-form-field";
44
import faker from "faker";
5+
import { AccessibilityLabels } from "../../enums/accessibility-labels";
56

67
describe("InputFormField", () => {
78
test("when default props, renders input with label", () => {
@@ -16,4 +17,132 @@ describe("InputFormField", () => {
1617
// Assert
1718
expect(getByLabelText(expected)).not.toBeNull();
1819
});
20+
21+
test("when errorsMessages prop set, renders with error messages", () => {
22+
// Arrange
23+
const errorMessages = [faker.random.words(), faker.random.words()];
24+
const label = faker.random.words();
25+
26+
// Act
27+
const { getByText } = render(
28+
<InputFormField
29+
errorMessages={errorMessages}
30+
label={label}
31+
onChange={() => {}}
32+
/>
33+
);
34+
35+
// Assert
36+
expect(getByText(errorMessages[0])).not.toBeNil();
37+
expect(getByText(errorMessages[1])).not.toBeNil();
38+
});
39+
40+
test("when errorsMessage prop set, renders with error message", () => {
41+
// Arrange
42+
const label = faker.random.words();
43+
const testErrorMessage = faker.random.words();
44+
45+
// Act
46+
const { getByText } = render(
47+
<InputFormField
48+
errorMessage={testErrorMessage}
49+
label={label}
50+
onChange={() => {}}
51+
/>
52+
);
53+
54+
// Assert
55+
expect(getByText(testErrorMessage)).not.toBeNil();
56+
});
57+
58+
test(`when isValid prop set to false, renders with ${InputFormFieldInvalidClass} class name`, () => {
59+
// Arrange
60+
const label = faker.random.words();
61+
62+
// Act
63+
const { container } = render(
64+
<InputFormField isValid={false} label={label} onChange={() => {}} />
65+
);
66+
const result = container.getElementsByClassName(
67+
InputFormFieldInvalidClass
68+
);
69+
70+
// Assert
71+
expect(result).toHaveLength(1);
72+
});
73+
74+
test(`when isValid prop set to true, renders without ${InputFormFieldInvalidClass} class name`, () => {
75+
// Arrange
76+
const label = faker.random.words();
77+
78+
// Act
79+
const { container } = render(
80+
<InputFormField isValid={true} label={label} onChange={() => {}} />
81+
);
82+
const result = container.getElementsByClassName(
83+
InputFormFieldInvalidClass
84+
);
85+
86+
// Assert
87+
expect(result).toHaveLength(0);
88+
});
89+
90+
test("when required prop set, renders with required text", () => {
91+
// Arrange
92+
const label = faker.random.words();
93+
const requiredText = "*";
94+
95+
// Act
96+
const { container } = render(
97+
<InputFormField label={label} onChange={() => {}} required={true} />
98+
);
99+
const htmlLabelTag = container.getElementsByTagName("label");
100+
101+
// Assert
102+
expect(htmlLabelTag[0].textContent).toContain(requiredText);
103+
});
104+
105+
test(`when showLabelForScreenReadersOnly prop set, renders with ${AccessibilityLabels.ScreenReadersOnlyClass} class name`, () => {
106+
// Arrange
107+
const label = faker.random.words();
108+
109+
// Act
110+
const { container } = render(
111+
<InputFormField
112+
label={label}
113+
onChange={() => {}}
114+
showLabelForScreenReadersOnly={true}
115+
/>
116+
);
117+
const htmlLabelTag = container.getElementsByTagName("span");
118+
119+
// Assert
120+
expect(htmlLabelTag[0].classList).toContain(
121+
AccessibilityLabels.ScreenReadersOnlyClass
122+
);
123+
});
124+
125+
test("when onChange set, calls handler upon change", () => {
126+
// Arrange
127+
let isChecked = false;
128+
const label = faker.random.word();
129+
const handleChange = () => (isChecked = true);
130+
const inputTestId = "inputTestId";
131+
132+
// Act
133+
const { getByTestId } = render(
134+
<InputFormField
135+
inputTestId={inputTestId}
136+
label={label}
137+
onChange={handleChange}
138+
/>
139+
);
140+
141+
fireEvent.change(getByTestId(inputTestId), {
142+
target: { value: faker.random.word() },
143+
});
144+
145+
// Assert
146+
expect(isChecked).toBeTrue();
147+
});
19148
});

src/molecules/form-fields/input-form-field.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { forwardRef, Ref, RefObject } from "react";
22
import uuid from "uuid";
3+
import { AccessibilityLabels } from "../../enums/accessibility-labels";
34
import { CollectionUtils, StringUtils } from "andculturecode-javascript-core";
45
import { InputCharacterCount } from "../../atoms/forms/input-character-count";
56
import { InputTypes } from "../../atoms/constants/input-types";
@@ -10,6 +11,7 @@ import { InputProperties } from "../../atoms/interfaces/input-properties";
1011
// -----------------------------------------------------------------------------------------
1112

1213
const COMPONENT_CLASS = "c-form-field";
14+
export const InputFormFieldInvalidClass = "-invalid";
1315

1416
// #endregion Constants
1517

@@ -64,14 +66,17 @@ const InputFormField: React.RefForwardingComponent<
6466
value,
6567
} = props;
6668

67-
const cssIsValid = isValid ? "" : "-invalid";
69+
const cssIsValid = isValid ? "" : InputFormFieldInvalidClass;
6870
const fieldId = props.fieldId ?? uuid.v4();
6971

7072
return (
7173
<div className={`${COMPONENT_CLASS} ${cssIsValid}`}>
7274
<label htmlFor={fieldId}>
7375
{showLabelForScreenReadersOnly ? (
74-
<span className="sr-only">{label}</span>
76+
<span
77+
className={AccessibilityLabels.ScreenReadersOnlyClass}>
78+
{label}
79+
</span>
7580
) : (
7681
<React.Fragment>{label}</React.Fragment>
7782
)}
@@ -82,7 +87,7 @@ const InputFormField: React.RefForwardingComponent<
8287
)}
8388
</label>
8489
<input
85-
data-test-id={inputTestId}
90+
data-testid={inputTestId}
8691
disabled={disabled}
8792
id={fieldId}
8893
placeholder={placeholder}

0 commit comments

Comments
 (0)