-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathpost-editor-07-markup.test.js
108 lines (84 loc) · 3.24 KB
/
post-editor-07-markup.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import 'jest-dom/extend-expect';
import 'react-testing-library/cleanup-after-each';
import React from 'react';
import {render, fireEvent, wait, waitForElement} from 'react-testing-library';
import {savePost as mockSavePost} from '../src/api';
import {Redirect as MockRedirect} from 'react-router-dom';
import {build, fake, sequence} from 'test-data-bot';
import {Editor} from '../src/post-editor-07-markup';
jest.mock('../src/api', () => ({
savePost: jest.fn(subject => Promise.resolve({ok: true})),
}));
jest.mock('react-router-dom', () => ({
Redirect: jest.fn(() => null),
}));
afterEach(() => {
MockRedirect.mockClear();
mockSavePost.mockClear();
});
const userBuilder = build('User').fields({
id: sequence(x => `user-${x}`),
});
const postBuilder = build('Post').fields({
content: fake(f => f.lorem.paragraphs().replace(/\r/g, '')),
tags: fake(f => f.lorem.words(3).split(' ')),
title: fake(f => f.lorem.sentence()),
});
describe('Editor', () => {
test('renders with correct fields and submit button', async () => {
const preDate = Date.now();
const fakeUser = userBuilder();
const payload = postBuilder();
const {container, getByLabelText, getByText} = render(
<Editor user={fakeUser} />
);
const titleInput = getByLabelText(/title/i);
const contentInput = getByLabelText(/content/i);
const tagsInput = getByLabelText(/tags/i);
titleInput.value = payload.title;
contentInput.value = payload.content;
tagsInput.value = payload.tags.join(', ');
const button = getByText(/submit/i);
fireEvent.click(button);
expect(button).toBeDisabled();
expect(mockSavePost).toHaveBeenCalledTimes(1);
expect(mockSavePost).toHaveBeenCalledWith({
...payload,
authorId: fakeUser.id,
date: expect.any(String),
});
const postDate = Date.now();
const date = new Date(mockSavePost.mock.calls[0][0].date).getTime();
expect(date).toBeGreaterThan(preDate);
expect(date).toBeLessThan(postDate);
await wait(() => {
expect(MockRedirect).toHaveBeenCalledTimes(1);
});
expect(MockRedirect).toHaveBeenCalledWith({to: '/'}, {});
});
test('renders an error when API rejects the request', async () => {
const error = 'test error';
// make mockSavePost reject once, and provide it with a value we can assert
// exists in the UI
mockSavePost.mockRejectedValueOnce({ok: false, message: error});
const fakeUser = userBuilder();
const payload = postBuilder();
const {container, getByLabelText, getByText, getByTestId} = render(
<Editor user={fakeUser} />
);
const contentInput = getByLabelText(/content/i);
const tagsInput = getByLabelText(/tags/i);
const titleInput = getByLabelText(/title/i);
contentInput.value = payload.content;
tagsInput.value = payload.tags.join(', ');
titleInput.value = payload.title;
const button = getByText(/submit/i);
fireEvent.click(button);
// Our element will only show after the promise is rejected.
// In order to get the element at a later point in time, we need to use
// waitForElement
const postErrorEl = await waitForElement(() => getByTestId('post-error'));
expect(postErrorEl).toHaveTextContent(error);
expect(button).not.toBeDisabled();
});
});