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

Tigers- Lindsey B. #116

Open
wants to merge 2 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
34 changes: 31 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
import React from 'react';
import './App.css';
import { useState } from 'react';
import chatMessages from './data/messages.json';
import ChatLog from './components/ChatLog';

const App = () => {
const [entries, setEntries] = useState(chatMessages);

const updateLike = () => {
let likeCount = 0;

for (const entry of entries) {
if (entry.liked === true) {
likeCount += 1;
}
}
return likeCount;
};

const toggleHeart = (id) => {
const newEntries = [];

for (const entry of entries) {
const newEntry = { ...entry };
if (newEntry.id === id) {
newEntry.liked = !newEntry.liked;
}
newEntries.push(newEntry);
}
setEntries(newEntries);
};

return (
<div id="App">
<header>
<h1>Application title</h1>
<h1>Chat with Estragon and Vladimir</h1>
<div> {updateLike()}❤️s</div>

Choose a reason for hiding this comment

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

As mentioned in my comment on Learn, this causes a test failure because our tests are expecting "3 ❤️s" with a space in between the number and the heart, while your code produces "3❤️s".

But this is a relatively minor issue, obviously.

</header>
<main>
{/* Wave 01: Render one ChatEntry component
Wave 02: Render ChatLog component */}
<ChatLog entries={entries} toggleHeartCallback={toggleHeart} />
</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('🤍');
});
});
34 changes: 28 additions & 6 deletions src/components/ChatEntry.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
import React from 'react';
import './ChatEntry.css';
import PropTypes from 'prop-types';
import TimeStamp from './TimeStamp';

const ChatEntry = (props) => {
const flipHeart = () => {
props.toggleHeartCallback(props.id);
};

return (
<div className="chat-entry local">
<h2 className="entry-name">Replace with name of sender</h2>
<div
className={`chat-entry ${
props.sender === 'Estragon' ? 'remote' : 'local'
} `}
Comment on lines +13 to +15

Choose a reason for hiding this comment

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

This works to distinguish the remote bubbles! Good job!

>
<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>{props.body}</p>
<p className="entry-time">
<TimeStamp time={props.timeStamp} />
</p>
<button className="like" onClick={flipHeart}>
{props.liked ? '❤️' : '🤍'}
</button>
</section>
</div>
);
};

ChatEntry.propTypes = {
//Fill with correct proptypes
id: PropTypes.number,
sender: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
timeStamp: PropTypes.string.isRequired,
liked: PropTypes.bool,
toggleHeartCallback: PropTypes.func,
};

ChatEntry.defaultProps = {
toggleHeartCallback: () => {},
};

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 React from 'react';
import PropTypes from 'prop-types';
import './ChatLog.css';
import ChatEntry from './ChatEntry';

const ChatLog = (props) => {
const chatEntryComponents = props.entries.map((entry) => {
return (
<ChatEntry
key={entry.id}
id={entry.id}
sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
toggleHeartCallback={props.toggleHeartCallback}

Choose a reason for hiding this comment

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

Since you use this toggleHeartCallback prop, it's likely a good idea to include it in your PropTypes below.

I would even recommend that it be .isRequired because this callback is pretty vital to the function of the code. However, that would cause issues with our tests, that do not supply this callback, so it'd be OK without .isRequired.

></ChatEntry>
);
});

return <div>{chatEntryComponents}</div>;
};

ChatLog.propTypes = {
entries: PropTypes.array.isRequired,
};

export default ChatLog;
7 changes: 7 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
// root.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>
// );
// Not sure if I need this code but it was in the live code, code gets sent into render method and once its rendered its injected
// directly into html inside the anchor div
Comment on lines +9 to +15

Choose a reason for hiding this comment

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

You don't need this code, and I verified that it works without it, but there is an advantage to keeping it. Namely, it will render the App component in strict mode, which doesn't produce any UI, but will produce warnings that may help you find bugs.

You can read more about it in the React docs on Strict Mode.