Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sea Turtles Natalia Woodson #90

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"luxon": "^2.4.0",
"moment": "^2.29.3",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1",
"luxon": "^2.4.0"
"react-scripts": "4.0.1"
},
"scripts": {
"start": "react-scripts start",
Expand Down
11 changes: 9 additions & 2 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#App header {
background-color: #222;
color: #fff;
/* color: #fff; */
padding-bottom: 0.5rem;
position: fixed;
width: 100%;
Expand All @@ -24,6 +24,7 @@
font-size: 1.5em;
text-align: center;
display: inline-block;
color: #fff;
}

#App header section {
Expand Down Expand Up @@ -71,4 +72,10 @@

.purple {
color: purple
}
}

.colorChoice {
display: flex;
justify-content: space-around;
}

50 changes: 46 additions & 4 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,58 @@
import React from 'react';
import React, { useState } from 'react';
import './App.css';
import ChatLog from './components/ChatLog';
import chatMessages from './data/messages.json';
import ColorChoice from './components/ColorChoice';

const App = () => {
const [chatData, setChatData] = useState(chatMessages);
const [localTextColor, setLocalTextColor] = useState('black');
const [remoteTextColor, setRemoteTextColor] = useState('black');

const updateChatData = (updatedEntry) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏽

const entries = chatData.map((entry) => {
if (entry.id === updatedEntry.id) {
return updatedEntry;
} else {
return entry;
}
});
setChatData(entries);
};

const totalLikes = chatData.reduce((total, entry) => {
if (entry.liked === true) {
total += 1;
}
return total;
}, 0);

return (
<div id="App">
<header>
<h1>Application title</h1>
<h1>
<div>Chat Log</div>
<div>{totalLikes} ❤️s</div>
</h1>
<section className="colorChoice">
<div>
<h3 className={localTextColor}>Vladimir's color</h3>
<ColorChoice onUpdateLocal={setLocalTextColor} />
</div>
<div>
<h3 className={remoteTextColor}>Estragon's color</h3>
<ColorChoice onUpdateRemote={setRemoteTextColor} />
</div>
</section>
</header>

<main>
{/* Wave 01: Render one ChatEntry component
Wave 02: Render ChatLog component */}
<ChatLog
entries={chatData}
onUpdateChat={updateChatData}
onUpdateLocal={localTextColor}
onUpdateRemote={remoteTextColor}
/>
</main>
</div>
);
Expand Down
60 changes: 30 additions & 30 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
import React from 'react'
import App from './App'
import { render, screen, fireEvent } from '@testing-library/react'
import React from 'react';
import App from './App';
import { render, screen, fireEvent } from '@testing-library/react';

describe('Wave 03: clicking like button and rendering App', () => {
test('that the correct number of likes is printed at the top', () => {
// Arrange
const { container } = render(<App />)
let buttons = container.querySelectorAll('button.like')
const { container } = render(<App />);
let buttons = container.querySelectorAll('button.like');

// Act
fireEvent.click(buttons[0])
fireEvent.click(buttons[1])
fireEvent.click(buttons[10])
fireEvent.click(buttons[0]);
fireEvent.click(buttons[1]);
fireEvent.click(buttons[10]);

// Assert
const countScreen = screen.getByText(/3 ❤️s/)
expect(countScreen).not.toBeNull()
})
const countScreen = screen.getByText(/3 ❤️s/);
expect(countScreen).not.toBeNull();
});

test('clicking button toggles heart and does not affect other buttons', () => {
// Arrange
const { container } = render(<App />)
const buttons = container.querySelectorAll('button.like')
const firstButton = buttons[0]
const lastButton = buttons[buttons.length - 1]
const { container } = render(<App />);
const buttons = container.querySelectorAll('button.like');
const firstButton = buttons[0];
const lastButton = buttons[buttons.length - 1];

// Act-Assert

// click the first button
fireEvent.click(firstButton)
expect(firstButton.innerHTML).toEqual('❤️')
fireEvent.click(firstButton);
expect(firstButton.innerHTML).toEqual('❤️');

// check that all other buttons haven't changed
for (let i = 1; i < buttons.length; i++) {
expect(buttons[i].innerHTML).toEqual('🤍')
expect(buttons[i].innerHTML).toEqual('🤍');
}

// click the first button a few more times
fireEvent.click(firstButton)
expect(firstButton.innerHTML).toEqual('🤍')
fireEvent.click(firstButton)
expect(firstButton.innerHTML).toEqual('❤️')
fireEvent.click(firstButton)
expect(firstButton.innerHTML).toEqual('🤍')
fireEvent.click(firstButton);
expect(firstButton.innerHTML).toEqual('🤍');
fireEvent.click(firstButton);
expect(firstButton.innerHTML).toEqual('❤️');
fireEvent.click(firstButton);
expect(firstButton.innerHTML).toEqual('🤍');

// click the last button a couple times
fireEvent.click(lastButton)
expect(lastButton.innerHTML).toEqual('❤️')
fireEvent.click(lastButton)
expect(lastButton.innerHTML).toEqual('🤍')
})
})
fireEvent.click(lastButton);
expect(lastButton.innerHTML).toEqual('❤️');
fireEvent.click(lastButton);
expect(lastButton.innerHTML).toEqual('🤍');
});
});
40 changes: 34 additions & 6 deletions src/components/ChatEntry.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,50 @@
import React from 'react';
import './ChatEntry.css';
import PropTypes from 'prop-types';
import TimeStamp from './TimeStamp';

const ChatEntry = (props) => {
const heartStatus = props.liked ? '❤️' : '🤍';
let entrySide =
props.sender === 'Vladimir' ? 'chat-entry local' : 'chat-entry remote';

let color =
props.sender === 'Vladimir' ? props.localTextColor : props.remoteTextColor;

const handleLike = () => {
const updatedEntry = {
id: props.id,
sender: props.sender,
body: props.body,
liked: !props.liked,
timeStamp: props.timeStamp,
};
props.onUpdate(updatedEntry);
};

return (
<div className="chat-entry local">
<h2 className="entry-name">Replace with name of sender</h2>
<div className={entrySide}>
<h2 className="entry-name">{props.sender}</h2>
<section className="entry-bubble">
<p>Replace with body of ChatEntry</p>
<p className="entry-time">Replace with TimeStamp component</p>
<button className="like">🤍</button>
<p className={color}>{props.body}</p>
<p className="entry-time">
<TimeStamp time={props.timeStamp} />
</p>
<button className="like" onClick={handleLike}>
{heartStatus}
</button>
</section>
</div>
);
};

ChatEntry.propTypes = {
//Fill with correct proptypes
id: PropTypes.number.isRequired,
sender: PropTypes.string,
body: PropTypes.string,
timestamp: PropTypes.string,
liked: PropTypes.bool,
onUpdate: PropTypes.func.isRequired,
Comment on lines +42 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Learn, we are seeing errors for some of your propTypes. I would only use isRequired on the props that must be passed for the component to render to pass the tests. In this case, the only required props would be the sender, body, timeStamp props.

};

export default ChatEntry;
16 changes: 8 additions & 8 deletions src/components/ChatEntry.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import "@testing-library/jest-dom/extend-expect";
import ChatEntry from "./ChatEntry";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import ChatEntry from './ChatEntry';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';

describe("Wave 01: ChatEntry", () => {
describe('Wave 01: ChatEntry', () => {
beforeEach(() => {
render(
<ChatEntry
Expand All @@ -14,15 +14,15 @@ describe("Wave 01: ChatEntry", () => {
);
});

test("renders without crashing and shows the sender", () => {
test('renders without crashing and shows the sender', () => {
expect(screen.getByText(/Joe Biden/)).toBeInTheDocument();
});

test("that it will display the body", () => {
test('that it will display the body', () => {
expect(screen.getByText(/Get out by 8am/)).toBeInTheDocument();
});

test("that it will display the time", () => {
test('that it will display the time', () => {
expect(screen.getByText(/\d+ years ago/)).toBeInTheDocument();
});
});
28 changes: 28 additions & 0 deletions src/components/ChatLog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import ChatEntry from './ChatEntry';
import PropTypes from 'prop-types';

const ChatLog = (props) => {
const chatEntries = props.entries.map((entry) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use index with map. This should get rid of your key on each child error.

const chatEntries = prop.entries.map((entry, i) => 
...
<ChatEntry
     key={i}

return (
<ChatEntry
key={entry.id}
id={entry.id}
sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
onUpdate={props.onUpdateChat}
localTextColor={props.onUpdateLocal}
remoteTextColor={props.onUpdateRemote}
></ChatEntry>
);
});
return <section className="chat-log">{chatEntries}</section>;
};

ChatLog.propTypes = {
entries: PropTypes.array.isRequired,
onUpdateChat: PropTypes.func.isRequired,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onUpdateChat is also giving a console error in learn. If you want this prop to be required then you could update the test to make sure it covers this prop as well or you can make it not required.

};

export default ChatLog;
38 changes: 38 additions & 0 deletions src/components/ColorChoice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';

const ColorChoice = (props) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this added feature!

const setColorCallback = (event) => {
if (props.onUpdateLocal) {
props.onUpdateLocal(event.currentTarget.id);
} else {
props.onUpdateRemote(event.currentTarget.id);
}
};

const getButtonsMap = () => {
const colors = {
red: '🔴',
yellow: '🟡',
purple: '🟣',
green: '🟢',
orange: '🟠',
blue: '🔵',
};
return Object.entries(colors).map(([key, value]) => {
return (
<button onClick={setColorCallback} key={key} id={key}>
{value}
</button>
);
});
};
return <div>{getButtonsMap()}</div>;
};

ColorChoice.propTypes = {
onUpdateLocal: PropTypes.func,
onUpdateRemote: PropTypes.func,
};

export default ColorChoice;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7374,6 +7374,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==

moment@^2.29.3:
version "2.29.3"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3"
integrity sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==

move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
Expand Down