Skip to content

Commit 8b9c28c

Browse files
committed
setup: useEffect to load messages
1 parent 132ce3d commit 8b9c28c

File tree

9 files changed

+153
-4
lines changed

9 files changed

+153
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@fortawesome/free-solid-svg-icons": "^5.12.0",
3030
"@fortawesome/react-fontawesome": "^0.1.8",
3131
"bootstrap": "^4.4.1",
32+
"faker": "^4.1.0",
3233
"react": "^16.12.0",
3334
"react-bootstrap": "^1.0.0-beta.16",
3435
"react-dom": "^16.12.0",

src/components/Feed/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from "react";
2+
import { Icon } from "../Icon";
3+
import { Message } from "../Message";
4+
import "./styles.css";
5+
6+
import fetchData from "../../services/api";
7+
8+
export const Feed = () => {
9+
const loading = true;
10+
const error = null;
11+
const data = null;
12+
13+
// TODO: useEffect to load state from fetchData
14+
fetchData("messages")
15+
.then(messages => {
16+
data = messages;
17+
loading = false;
18+
})
19+
.catch(error => {
20+
error = error;
21+
});
22+
23+
if (loading) {
24+
return (
25+
<div className="Feed">
26+
<div className="Feed_Loading" title="loading">
27+
<Icon icon="loading" spin size="lg" data-testid="loading" />
28+
</div>
29+
</div>
30+
);
31+
}
32+
33+
if (error) {
34+
return <div title="error">{error.message}</div>;
35+
}
36+
37+
return (
38+
<div className="Feed" title="feed">
39+
{data.map(post => (
40+
<Message key={post.id_str} {...post} />
41+
))}
42+
</div>
43+
);
44+
};

src/components/Feed/styles.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.Feed {
2+
background-color: "red";
3+
}
4+
5+
.Feed_Loading {
6+
display: flex;
7+
justify-content: center;
8+
padding-top: 30px;
9+
}

src/services/api.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as faker from 'faker'
2+
3+
const api = async url => {
4+
// sign up for a developer twitter account to get real tweets
5+
// examples at https://api.twitter.com/1.1/search/tweets.json
6+
7+
// fake api delay
8+
await new Promise((resolve, reject) => {
9+
setTimeout(resolve, 1500)
10+
})
11+
12+
// fake api
13+
switch (url) {
14+
case 'messages':
15+
// generate fake data
16+
const fakeMessages = [1, 2, 3, 4, 5, 6].map(() => ({
17+
id_str: faker.random.uuid(),
18+
created_at: faker.date.recent().toISOString(),
19+
text: faker.lorem.paragraph(),
20+
retweet_count: faker.random.number(50),
21+
retweeted: false,
22+
favorite_count: faker.random.number(50),
23+
favorited: false,
24+
user: {
25+
id_str: faker.random.uuid(),
26+
name: faker.internet.userName(),
27+
screen_name: faker.internet.userName(),
28+
profile_image_url_https: faker.image.avatar(),
29+
},
30+
}))
31+
32+
return fakeMessages
33+
default:
34+
throw new Error('Unknown API endpoint')
35+
}
36+
}
37+
38+
export default api

src/stories/2-Message.stories.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from "react";
22
import { Message as UseStateMessage } from "../components/Message/useState";
3-
import { Message as UseReducerMessage } from "../components/Message/useReducer";
3+
import { Message as UseReducerMessage } from "../components/Message";
44
import { USER } from "../config";
55

66
export default {

src/stories/3-Feed.stories.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from "react";
2+
import { Feed } from "../components/Feed";
3+
4+
export default {
5+
title: "Feed"
6+
};
7+
8+
export const feed = () => {
9+
return <Feed />;
10+
};

src/tests/components/Feed.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from "react";
2+
import { render } from "@testing-library/react";
3+
import { waitForElementToBeRemoved } from "@testing-library/dom";
4+
import { Feed } from "../../components/Feed";
5+
6+
const mockData = [
7+
{
8+
id_str: "1",
9+
created_at: new Date().toISOString(),
10+
text: "Some text",
11+
retweet_count: 10,
12+
retweeted: false,
13+
favorite_count: 15,
14+
favorited: false,
15+
user: {
16+
id_str: "u1",
17+
name: "Some User",
18+
screen_name: "someUser",
19+
profile_image_url_https: ""
20+
}
21+
}
22+
];
23+
24+
jest.mock("../../services/api.js", () => jest.fn(async () => mockData));
25+
26+
// UI
27+
28+
describe("Feed", () => {
29+
// generated useEffect async warnings
30+
test("should initially display loading", () => {
31+
const utils = render(<Feed />);
32+
const loading = utils.getByTitle("loading");
33+
expect(loading).toBeDefined();
34+
const feed = utils.queryByTitle("feed"); // query doesn't throw
35+
expect(feed).toBe(null);
36+
});
37+
38+
test("should display feed when loaded", async () => {
39+
const utils = render(<Feed />);
40+
41+
await waitForElementToBeRemoved(() => {
42+
return utils.getByTestId("loading");
43+
});
44+
const feed = utils.getByTitle("feed");
45+
expect(feed).toBeDefined();
46+
});
47+
});

src/tests/components/Message.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from "react";
22
import { render, fireEvent } from "@testing-library/react";
3-
import { Message, messageReducer } from "../../components/Message/useReducer";
3+
import { Message, messageReducer } from "../../components/Message";
44
import { USER } from "../../config";
55

66
const mockProps = {
@@ -13,7 +13,7 @@ const mockProps = {
1313
favorite_count: 22
1414
};
1515

16-
describe("Message", () => {
16+
describe.skip("Message", () => {
1717
test("should display the initial favorite count", () => {
1818
const utils = render(<Message {...mockProps} />);
1919
const count = utils.getByTitle("favorite_count");
@@ -68,7 +68,7 @@ const initialState = {
6868
favorite_count: 22
6969
};
7070

71-
describe("messageReducer", () => {
71+
describe.skip("messageReducer", () => {
7272
test("should display the initial values", () => {
7373
const returnsState = messageReducer(initialState, { type: "UNKNOWN" });
7474
expect(returnsState).toEqual(initialState);

0 commit comments

Comments
 (0)