Skip to content

Commit 829d85f

Browse files
committed
feat(notifications): Add base for notification scope
1 parent a3bd63c commit 829d85f

4 files changed

Lines changed: 174 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const getNotifications = async () => null;
2+
3+
export default {
4+
getNotifications,
5+
};

src/notifications/Notifications.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// @flow
2+
3+
import * as React from "react";
4+
import NotificationService from "./NotificationService";
5+
6+
type Props = {
7+
user: User,
8+
children: ({
9+
alerts: Array<Alert>,
10+
messages: Array<Message>,
11+
}) => React.Node,
12+
};
13+
14+
type State = {
15+
alerts: Array<Alert>,
16+
messages: Array<Message>,
17+
};
18+
19+
export class Notifications extends React.Component<Props, State> {
20+
state = {
21+
alerts: [],
22+
messages: [],
23+
};
24+
25+
componentDidMount() {
26+
this.updateUserNotifications();
27+
}
28+
29+
getChildrenProps() {
30+
const { alerts, messages } = this.state;
31+
32+
return {
33+
alerts,
34+
messages,
35+
};
36+
}
37+
38+
async updateUserNotifications() {
39+
const { unread_notifications: unreadNotifications } = this.props.user;
40+
41+
if (unreadNotifications > 0) {
42+
const { notifications } = await NotificationService.getNotifications();
43+
44+
this.setState({
45+
alerts: [notifications[0]],
46+
messages: [notifications[1]],
47+
});
48+
49+
return true;
50+
}
51+
52+
return false;
53+
}
54+
55+
render() {
56+
return this.props.children(this.getChildrenProps());
57+
}
58+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
name: Notifications
3+
---
4+
5+
# Notifications
6+
7+
Use a given user object in order to fetch the user notifications and inject them in a normalised shape to its children
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// @flow
2+
jest.mock("../NotificationService");
3+
4+
import "jest-dom/extend-expect";
5+
import { Notifications } from "../Notifications";
6+
import NotificationService from "../NotificationService";
7+
import React from "react";
8+
import { cleanup, render, waitForElement } from "react-testing-library";
9+
10+
const renderNotifications = (props: Object) => {
11+
return render(
12+
<Notifications {...props}>
13+
{({ alerts, messages }) => {
14+
return (
15+
<div data-testid="data">
16+
<div data-testid="alerts">{JSON.stringify(alerts)}</div>
17+
<div data-testid="messages">{JSON.stringify(messages)}</div>
18+
</div>
19+
);
20+
}}
21+
</Notifications>
22+
);
23+
};
24+
25+
const notificationsData = {
26+
notifications: [
27+
{
28+
created_at: "2019-02-16T14:37:18.891Z",
29+
data: {
30+
display_username: "system",
31+
group_id: 1,
32+
topic_title: "Backup failed",
33+
},
34+
fancy_title: "Backup failed",
35+
id: 1,
36+
notification_type: 7,
37+
post_number: 1,
38+
read: false,
39+
slug: "backup-failed",
40+
topic_id: 11,
41+
},
42+
{
43+
created_at: "2019-03-24T10:24:32.495Z",
44+
data: {
45+
display_username: "janedoe",
46+
original_post_id: 41,
47+
original_post_type: 1,
48+
original_username: "janedoe",
49+
revision_number: null,
50+
topic_title: "Hello, I'm Jane Doe",
51+
},
52+
fancy_title: "Hello, I&rsquo;m Jane Doe",
53+
id: 18,
54+
notification_type: 6,
55+
post_number: 1,
56+
read: false,
57+
slug: "hello-im-jane-doe",
58+
topic_id: 26,
59+
},
60+
],
61+
};
62+
63+
describe("<Notifications />", () => {
64+
afterEach(() => {
65+
cleanup();
66+
jest.clearAllMocks();
67+
});
68+
69+
it("renders props of shaped object of messages and alerts", async () => {
70+
const userData = {
71+
unread_notifications: 10,
72+
username: "johndoe",
73+
};
74+
NotificationService.getNotifications = jest
75+
.fn()
76+
.mockResolvedValue(notificationsData);
77+
const { getByTestId } = renderNotifications({ user: userData });
78+
const alertsElem = await waitForElement(() => getByTestId("alerts"));
79+
const messagesElem = await waitForElement(() => getByTestId("messages"));
80+
81+
expect(NotificationService.getNotifications).toBeCalledTimes(1);
82+
expect(alertsElem.firstChild).toMatchInlineSnapshot(
83+
"[{\"created_at\":\"2019-02-16T14:37:18.891Z\",\"data\":{\"display_username\":\"system\",\"group_id\":1,\"topic_title\":\"Backup failed\"},\"fancy_title\":\"Backup failed\",\"id\":1,\"notification_type\":7,\"post_number\":1,\"read\":false,\"slug\":\"backup-failed\",\"topic_id\":11}]"
84+
);
85+
expect(messagesElem.firstChild).toMatchInlineSnapshot(
86+
"[{\"created_at\":\"2019-03-24T10:24:32.495Z\",\"data\":{\"display_username\":\"janedoe\",\"original_post_id\":41,\"original_post_type\":1,\"original_username\":\"janedoe\",\"revision_number\":null,\"topic_title\":\"Hello, I'm Jane Doe\"},\"fancy_title\":\"Hello, I&rsquo;m Jane Doe\",\"id\":18,\"notification_type\":6,\"post_number\":1,\"read\":false,\"slug\":\"hello-im-jane-doe\",\"topic_id\":26}]"
87+
);
88+
});
89+
90+
describe("when there is no unread notifications", () => {
91+
it("renders props of shaped object with empty data", async () => {
92+
const userData = {
93+
unread_notifications: 0,
94+
};
95+
const { getByTestId } = renderNotifications({ user: userData });
96+
const alertsElem = await waitForElement(() => getByTestId("alerts"));
97+
const messagesElem = await waitForElement(() => getByTestId("messages"));
98+
99+
expect(NotificationService.getNotifications).toBeCalledTimes(0);
100+
expect(alertsElem.firstChild).toMatchInlineSnapshot("[]");
101+
expect(messagesElem.firstChild).toMatchInlineSnapshot("[]");
102+
});
103+
});
104+
});

0 commit comments

Comments
 (0)