Skip to content

Commit d42da87

Browse files
authored
Merge pull request #10 from itsGabeB/solved-components
Solved components
2 parents 4e50ae3 + 966c4ba commit d42da87

10 files changed

Lines changed: 458 additions & 24 deletions

File tree

public/tasks/task-components.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Task - Components
2+
3+
Version: 0.0.1
4+
5+
Fix some components that are using state incorrectly.

src/App.tsx

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,48 +14,40 @@ import { ChangeType } from "./components/ChangeType";
1414
import { StartAttempt } from "./components/StartAttempt";
1515
import { TwoDice } from "./components/TwoDice";
1616
import { CycleHoliday } from "./components/CycleHoliday";
17+
//import { Counter } from "./components/Counter";
18+
import { DoubleHalf } from "./bad-components/DoubleHalf";
19+
20+
import { ColoredBox } from "./bad-components/ColoredBox";
21+
import { ShoveBox } from "./bad-components/ShoveBox";
22+
23+
import { ChooseTeam } from "./bad-components/ChooseTeam";
1724

1825
export function App(): React.JSX.Element {
1926
return (
2027
<div className="App">
2128
<header className="App-header">
2229
UD CISC275 with React Hooks and TypeScript
2330
</header>
24-
31+
<hr></hr>
32+
<DoubleHalf></DoubleHalf>
33+
<hr></hr>
34+
<ChooseTeam></ChooseTeam>
35+
<hr></hr>
36+
<ColoredBox></ColoredBox>
37+
<hr></hr>
38+
<ShoveBox></ShoveBox>
39+
<hr></hr>
2540
<Counter></Counter>
2641
<hr />
27-
2842
<RevealAnswer></RevealAnswer>
2943
<hr />
30-
3144
<StartAttempt></StartAttempt>
3245
<hr />
33-
3446
<TwoDice></TwoDice>
3547
<hr />
36-
3748
<ChangeType></ChangeType>
3849
<hr />
39-
4050
<CycleHoliday></CycleHoliday>
4151
</div>
4252
);
4353
}
44-
/*
45-
<header className="App-header">
46-
UD CISC275 with React Hooks and TypeScript
47-
</header>
48-
{/*
49-
<hr>
50-
<Counter></Counter>
51-
<hr />
52-
<RevealAnswer></RevealAnswer>
53-
<hr />
54-
<StartAttempt></StartAttempt>
55-
<hr />
56-
<TwoDice></TwoDice>
57-
<hr />
58-
<ChangeType></ChangeType>
59-
<hr />
60-
<CycleHoliday></CycleHoliday>
61-
*/
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, { act } from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import { ChooseTeam } from "./ChooseTeam";
4+
5+
describe("ChooseTeam Component tests", () => {
6+
beforeEach(() => {
7+
render(<ChooseTeam />);
8+
});
9+
test("(2 pts) The initial team is empty", () => {
10+
const currentTeam = screen.queryAllByRole("listitem");
11+
expect(currentTeam).toHaveLength(0);
12+
});
13+
test("(2 pts) There are 7 buttons.", () => {
14+
const adders = screen.queryAllByRole("button");
15+
expect(adders).toHaveLength(7);
16+
});
17+
test("(2 pts) Clicking first team member works", async () => {
18+
const first = screen.queryAllByRole("button")[0];
19+
await act(async () => {
20+
first.click();
21+
});
22+
const currentTeam = screen.queryAllByRole("listitem");
23+
expect(currentTeam).toHaveLength(1);
24+
expect(currentTeam[0].textContent).toEqual(first.textContent);
25+
});
26+
test("(2 pts) Clicking the third team member works", async () => {
27+
const third = screen.queryAllByRole("button")[2];
28+
await act(async () => {
29+
third.click();
30+
});
31+
const currentTeam = screen.queryAllByRole("listitem");
32+
expect(currentTeam).toHaveLength(1);
33+
expect(currentTeam[0].textContent).toEqual(third.textContent);
34+
});
35+
test("(2 pts) Clicking three team members works", async () => {
36+
const [, second, third, , fifth] = screen.queryAllByRole("button");
37+
await act(async () => {
38+
third.click();
39+
});
40+
await act(async () => {
41+
second.click();
42+
});
43+
await act(async () => {
44+
fifth.click();
45+
});
46+
const currentTeam = screen.queryAllByRole("listitem");
47+
expect(currentTeam).toHaveLength(3);
48+
expect(currentTeam[0].textContent).toEqual(third.textContent);
49+
expect(currentTeam[1].textContent).toEqual(second.textContent);
50+
expect(currentTeam[2].textContent).toEqual(fifth.textContent);
51+
});
52+
test("(2 pts) Clearing the team works", async () => {
53+
const [, second, third, fourth, fifth, , clear] =
54+
screen.queryAllByRole("button");
55+
await act(async () => {
56+
third.click();
57+
});
58+
await act(async () => {
59+
second.click();
60+
});
61+
await act(async () => {
62+
fifth.click();
63+
});
64+
let currentTeam = screen.queryAllByRole("listitem");
65+
expect(currentTeam).toHaveLength(3);
66+
expect(currentTeam[0].textContent).toEqual(third.textContent);
67+
expect(currentTeam[1].textContent).toEqual(second.textContent);
68+
expect(currentTeam[2].textContent).toEqual(fifth.textContent);
69+
await act(async () => {
70+
clear.click();
71+
});
72+
currentTeam = screen.queryAllByRole("listitem");
73+
expect(currentTeam).toHaveLength(0);
74+
await act(async () => {
75+
fourth.click();
76+
});
77+
currentTeam = screen.queryAllByRole("listitem");
78+
expect(currentTeam).toHaveLength(1);
79+
expect(currentTeam[0].textContent).toEqual(fourth.textContent);
80+
});
81+
});

src/bad-components/ChooseTeam.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { useState } from "react";
2+
import { Button, Row, Col } from "react-bootstrap";
3+
4+
const PEOPLE = [
5+
"Alan Turing",
6+
"Grace Hopper",
7+
"Ada Lovelace",
8+
"Charles Babbage",
9+
"Barbara Liskov",
10+
"Margaret Hamilton",
11+
];
12+
13+
export function ChooseTeam(): React.JSX.Element {
14+
const [allOptions] = useState<string[]>(PEOPLE);
15+
const [team, setTeam] = useState<string[]>([]);
16+
17+
function chooseMember(newMember: string) {
18+
/*
19+
if (!team.includes(newMember)) {
20+
team.push(newMember);
21+
}
22+
*/
23+
if (!team.find((member: string): boolean => member === newMember)) {
24+
setTeam([...team, newMember]);
25+
}
26+
}
27+
28+
function clearTeam() {
29+
setTeam([]);
30+
}
31+
32+
return (
33+
<div>
34+
<h3>Choose Team</h3>
35+
<Row>
36+
<Col>
37+
{allOptions.map((option: string) => (
38+
<div key={option} style={{ marginBottom: "4px" }}>
39+
Add{" "}
40+
<Button
41+
onClick={() => {
42+
chooseMember(option);
43+
}}
44+
size="sm"
45+
>
46+
{option}
47+
</Button>
48+
</div>
49+
))}
50+
</Col>
51+
<Col>
52+
<strong>Team:</strong>
53+
{team.map((member: string) => (
54+
<li key={member}>{member}</li>
55+
))}
56+
<Button onClick={clearTeam}>Clear Team</Button>
57+
</Col>
58+
</Row>
59+
</div>
60+
);
61+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React, { act } from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import { ColoredBox } from "./ColoredBox";
4+
5+
describe("ColoredBox Component tests", () => {
6+
beforeEach(() => {
7+
render(<ColoredBox />);
8+
});
9+
test("(2 pts) The ColoredBox is initially red.", () => {
10+
const box = screen.getByTestId("colored-box");
11+
expect(box).toHaveStyle({ backgroundColor: "red" });
12+
});
13+
test("(2 pts) There is a button", () => {
14+
expect(screen.getByRole("button")).toBeInTheDocument();
15+
});
16+
test("(2 pts) Clicking the button advances the color.", async () => {
17+
const nextColor = screen.getByRole("button");
18+
await act(async () => {
19+
nextColor.click();
20+
});
21+
expect(screen.getByTestId("colored-box")).toHaveStyle({
22+
backgroundColor: "blue",
23+
});
24+
await act(async () => {
25+
nextColor.click();
26+
});
27+
expect(screen.getByTestId("colored-box")).toHaveStyle({
28+
backgroundColor: "green",
29+
});
30+
await act(async () => {
31+
nextColor.click();
32+
});
33+
expect(screen.getByTestId("colored-box")).toHaveStyle({
34+
backgroundColor: "red",
35+
});
36+
});
37+
});

src/bad-components/ColoredBox.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { useState } from "react";
2+
import { Button } from "react-bootstrap";
3+
4+
export const COLORS = ["red", "blue", "green"];
5+
const DEFAULT_COLOR_INDEX = 0;
6+
7+
interface colorProp {
8+
setColorIndex(colorNum: number): void;
9+
colorIndex: number;
10+
}
11+
interface colorNumSolo {
12+
colorIndex: number;
13+
}
14+
15+
function ChangeColor({
16+
setColorIndex,
17+
colorIndex,
18+
}: colorProp): React.JSX.Element {
19+
return (
20+
<Button
21+
onClick={() => {
22+
setColorIndex((1 + colorIndex) % COLORS.length);
23+
}}
24+
>
25+
Next Color
26+
</Button>
27+
);
28+
}
29+
30+
function ColorPreview({ colorIndex }: colorNumSolo): React.JSX.Element {
31+
return (
32+
<div
33+
data-testid="colored-box"
34+
style={{
35+
width: "50px",
36+
height: "50px",
37+
backgroundColor: COLORS[colorIndex],
38+
display: "inline-block",
39+
verticalAlign: "bottom",
40+
marginLeft: "5px",
41+
}}
42+
></div>
43+
);
44+
}
45+
46+
export function ColoredBox(): React.JSX.Element {
47+
const [colorIndex, setColorIndex] = useState<number>(DEFAULT_COLOR_INDEX);
48+
return (
49+
<div>
50+
<h3>Colored Box</h3>
51+
<span>The current color is: {COLORS[colorIndex]}</span>
52+
<div>
53+
<ChangeColor
54+
setColorIndex={setColorIndex}
55+
colorIndex={colorIndex}
56+
></ChangeColor>
57+
<ColorPreview colorIndex={colorIndex}></ColorPreview>
58+
</div>
59+
</div>
60+
);
61+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { act } from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import { DoubleHalf } from "./DoubleHalf";
4+
5+
describe("DoubleHalf Component tests", () => {
6+
beforeEach(() => {
7+
render(<DoubleHalf />);
8+
});
9+
test("(2 pts) The DoubleHalf value is initially 10", () => {
10+
expect(screen.getByText("10")).toBeInTheDocument();
11+
expect(screen.queryByText("20")).not.toBeInTheDocument();
12+
expect(screen.queryByText("5")).not.toBeInTheDocument();
13+
});
14+
test("(2 pts) There are Double and Halve buttons", () => {
15+
expect(
16+
screen.getByRole("button", { name: /Double/i }),
17+
).toBeInTheDocument();
18+
expect(
19+
screen.getByRole("button", { name: /Halve/i }),
20+
).toBeInTheDocument();
21+
});
22+
test("(2 pts) You can double the number.", async () => {
23+
const double = screen.getByRole("button", { name: /Double/i });
24+
await act(async () => {
25+
double.click();
26+
});
27+
expect(screen.getByText("20")).toBeInTheDocument();
28+
expect(screen.queryByText("10")).not.toBeInTheDocument();
29+
});
30+
test("(2 pts) You can halve the number.", async () => {
31+
const halve = screen.getByRole("button", { name: /Halve/i });
32+
await act(async () => {
33+
halve.click();
34+
});
35+
expect(screen.getByText("5")).toBeInTheDocument();
36+
expect(screen.queryByText("10")).not.toBeInTheDocument();
37+
});
38+
test("(2 pts) You can double AND halve the number.", async () => {
39+
const double = screen.getByRole("button", { name: /Double/i });
40+
const halve = screen.getByRole("button", { name: /Halve/i });
41+
await act(async () => {
42+
double.click();
43+
});
44+
expect(screen.getByText("20")).toBeInTheDocument();
45+
expect(screen.queryByText("10")).not.toBeInTheDocument();
46+
await act(async () => {
47+
double.click();
48+
});
49+
expect(screen.getByText("40")).toBeInTheDocument();
50+
expect(screen.queryByText("20")).not.toBeInTheDocument();
51+
await act(async () => {
52+
halve.click();
53+
});
54+
expect(screen.getByText("20")).toBeInTheDocument();
55+
expect(screen.queryByText("10")).not.toBeInTheDocument();
56+
await act(async () => {
57+
halve.click();
58+
});
59+
expect(screen.getByText("10")).toBeInTheDocument();
60+
expect(screen.queryByText("20")).not.toBeInTheDocument();
61+
await act(async () => {
62+
halve.click();
63+
});
64+
expect(screen.getByText("5")).toBeInTheDocument();
65+
expect(screen.queryByText("10")).not.toBeInTheDocument();
66+
await act(async () => {
67+
halve.click();
68+
});
69+
expect(screen.getByText("2.5")).toBeInTheDocument();
70+
expect(screen.queryByText("5")).not.toBeInTheDocument();
71+
});
72+
});

0 commit comments

Comments
 (0)