/
postsV2.js
296 lines (255 loc) · 12 KB
/
postsV2.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/* eslint-env node, mocha */
/* global $pg_database */
import fetch from 'node-fetch'
import expect from 'unexpected'
import cleanDB from '../dbCleaner'
import { getSingleton } from '../../app/app'
import { DummyPublisher } from '../../app/pubsub'
import { PubSub } from '../../app/models'
import {
createUserAsync,
createAndReturnPost,
createCommentAsync,
like,
goPrivate,
goProtected,
mutualSubscriptions,
fetchPost,
createMockAttachmentAsync,
updatePostAsync,
hidePost,
} from './functional_test_helper'
describe('TimelinesControllerV2', () => {
let app;
let fetchPostOpenGraph;
before(async () => {
app = await getSingleton();
fetchPostOpenGraph = postOpenGraphFetcher(app);
PubSub.setPublisher(new DummyPublisher());
});
beforeEach(() => cleanDB($pg_database));
describe('#postsV2', () => {
describe('Luna wrote post, Mars is mutual friend, Venus is stranger', () => {
let luna, mars, venus;
let lunaPost;
beforeEach(async () => {
[luna, mars, venus] = await Promise.all([
createUserAsync('luna', 'pw'),
createUserAsync('mars', 'pw'),
createUserAsync('venus', 'pw'),
]);
lunaPost = await createAndReturnPost(luna, 'Luna post');
await mutualSubscriptions([luna, mars]);
});
describe('Comments folding test', () => {
const expectFolding = async (nComments, expComments, expOmitted, allComments = false) => {
for (let n = 0; n < nComments; n++) {
await createCommentAsync(luna, lunaPost.id, `Comment ${n + 1}`); // eslint-disable-line no-await-in-loop
}
const post = await fetchPost(lunaPost.id, null, { allComments });
expect(post.posts.comments, 'to have length', expComments);
expect(post.posts.omittedComments, 'to equal', expOmitted);
};
describe('Folded comments', () => {
it('should return post whith 1 comment without folding', async () => await expectFolding(1, 1, 0));
it('should return post whith 2 comments without folding', async () => await expectFolding(2, 2, 0));
it('should return post whith 3 comments without folding', async () => await expectFolding(3, 3, 0));
it('should return post whith 4 comments with folding', async () => await expectFolding(4, 2, 2));
it('should return post whith 5 comments with folding', async () => await expectFolding(5, 2, 3));
});
describe('Unfolded comments', () => {
it('should return post whith 1 comment without folding', async () => await expectFolding(1, 1, 0, true));
it('should return post whith 2 comments without folding', async () => await expectFolding(2, 2, 0, true));
it('should return post whith 3 comments without folding', async () => await expectFolding(3, 3, 0, true));
it('should return post whith 4 comments without folding', async () => await expectFolding(4, 4, 0, true));
it('should return post whith 5 comments without folding', async () => await expectFolding(5, 5, 0, true));
});
});
describe('Likes folding test', () => {
let users;
beforeEach(async () => {
const promises = [];
for (let n = 0; n < 5; n++) {
promises.push(createUserAsync(`username${n + 1}`, 'pw'));
}
users = await Promise.all(promises);
});
const expectFolding = async (nLikes, expLikes, expOmitted, allLikes = false) => {
await Promise.all(users.slice(0, nLikes).map((u) => like(lunaPost.id, u.authToken)));
const post = await fetchPost(lunaPost.id, null, { allLikes });
expect(post.posts.likes, 'to have length', expLikes);
expect(post.posts.omittedLikes, 'to equal', expOmitted);
};
describe('Folded likes', () => {
it('should return post whith 1 like without folding', async () => await expectFolding(1, 1, 0));
it('should return post whith 2 likes without folding', async () => await expectFolding(2, 2, 0));
it('should return post whith 3 likes without folding', async () => await expectFolding(3, 3, 0));
it('should return post whith 4 likes without folding', async () => await expectFolding(4, 4, 0));
it('should return post whith 5 likes with folding', async () => await expectFolding(5, 3, 2));
});
describe('Unfolded likes', () => {
it('should return post whith 1 like without folding', async () => await expectFolding(1, 1, 0, true));
it('should return post whith 2 likes without folding', async () => await expectFolding(2, 2, 0, true));
it('should return post whith 3 likes without folding', async () => await expectFolding(3, 3, 0, true));
it('should return post whith 4 likes without folding', async () => await expectFolding(4, 4, 0, true));
it('should return post whith 5 likes without folding', async () => await expectFolding(5, 5, 0, true));
});
});
describe('Luna is a public user', () => {
it('should return post to anonymous', async () => {
const post = await fetchPost(lunaPost.id);
expect(post.posts.id, 'to be', lunaPost.id);
});
it('should return post to Luna', async () => {
const post = await fetchPost(lunaPost.id, luna);
expect(post.posts.id, 'to be', lunaPost.id);
});
it('should return post to Venus', async () => {
const post = await fetchPost(lunaPost.id, venus);
expect(post.posts.id, 'to be', lunaPost.id);
});
});
describe('Luna is a protected user', () => {
beforeEach(async () => await goProtected(luna));
it('should not return post to anonymous', async () => {
const resp = await fetchPost(lunaPost.id, null, { returnError: true });
expect(resp, 'to satisfy', { status: 403 });
});
it('should return post to Luna', async () => {
const post = await fetchPost(lunaPost.id, luna);
expect(post.posts.id, 'to be', lunaPost.id);
});
it('should return post to Venus', async () => {
const post = await fetchPost(lunaPost.id, venus);
expect(post.posts.id, 'to be', lunaPost.id);
});
});
describe('Luna is a private user', () => {
beforeEach(async () => await goPrivate(luna));
it('should not return post to anonymous', async () => {
const resp = await fetchPost(lunaPost.id, null, { returnError: true });
expect(resp, 'to satisfy', { status: 403 });
});
it('should return post to Luna', async () => {
const post = await fetchPost(lunaPost.id, luna);
expect(post.posts.id, 'to be', lunaPost.id);
});
it('should not return post to Venus', async () => {
const resp = await fetchPost(lunaPost.id, venus, { returnError: true });
expect(resp, 'to satisfy', { status: 403 });
});
it('should return post to Mars', async () => {
const post = await fetchPost(lunaPost.id, mars);
expect(post.posts.id, 'to be', lunaPost.id);
});
});
describe('Open Graph test', () => {
let lunaPostWithSpecialCharacters, lunaPostWithNewLines;
beforeEach(async () => {
lunaPostWithSpecialCharacters = await createAndReturnPost(luna, 'Test with tags <br>');
lunaPostWithNewLines = await createAndReturnPost(luna, 'A\nB\nC');
});
describe('Luna is a public user', () => {
it('should return information for a public post', async () => {
const response = await fetchPostOpenGraph(lunaPost.id);
response.should.include('og:title');
response.should.include('luna');
response.should.include('<meta property="og:description" content="Luna post" />');
});
it('should escape special characters', async () => {
const response = await fetchPostOpenGraph(lunaPostWithSpecialCharacters.id);
response.should.include('<meta property="og:description" content="Test with tags <br>" />');
});
it('should support new lines', async () => {
const response = await fetchPostOpenGraph(lunaPostWithNewLines.id);
response.should.include('<meta property="og:description" content="A\nB\nC" />');
});
});
describe('Luna is a protected user', () => {
beforeEach(async () => await goProtected(luna));
it('should not return any information for a protected post', async () => {
const response = await fetchPostOpenGraph(lunaPost.id);
response.should.be.empty;
});
});
describe('Luna is a private user', () => {
beforeEach(async () => await goPrivate(luna));
it('should not return any information for a private post', async () => {
const response = await fetchPostOpenGraph(lunaPost.id);
response.should.be.empty;
});
});
});
});
describe('Luna wrote post and 3 attachments', () => {
let luna;
let attId1, attId2, attId3;
beforeEach(async () => {
luna = await createUserAsync('luna', 'pw');
luna.post = await createAndReturnPost(luna, 'Luna post');
attId1 = (await createMockAttachmentAsync(luna)).id;
attId2 = (await createMockAttachmentAsync(luna)).id;
attId3 = (await createMockAttachmentAsync(luna)).id;
});
it('should return post with [1, 2, 3] attachments in the correct order', async () => {
const postData = {
body: luna.post.body,
attachments: [attId1, attId2, attId3],
};
await updatePostAsync(luna, postData);
const { posts } = await fetchPost(luna.post.id);
expect(posts.attachments, 'to equal', postData.attachments);
});
it('should return post with [3, 1, 2] attachments in the correct order', async () => {
const postData = {
body: luna.post.body,
attachments: [attId3, attId1, attId2],
};
await updatePostAsync(luna, postData);
const { posts } = await fetchPost(luna.post.id);
expect(posts.attachments, 'to equal', postData.attachments);
});
it('should return post after attachment deletion with attachments in the correct order', async () => {
const postData = {
body: luna.post.body,
attachments: [attId3, attId1, attId2],
};
await updatePostAsync(luna, postData);
postData.attachments = [attId3, attId2];
await updatePostAsync(luna, postData);
const { posts } = await fetchPost(luna.post.id);
expect(posts.attachments, 'to equal', postData.attachments);
});
it('should return post after attachment addition with attachments in the correct order', async () => {
const postData = {
body: luna.post.body,
attachments: [attId1, attId2],
};
await updatePostAsync(luna, postData);
postData.attachments = [attId3, attId2, attId1];
await updatePostAsync(luna, postData);
const { posts } = await fetchPost(luna.post.id);
expect(posts.attachments, 'to equal', postData.attachments);
});
});
describe('Luna wrote post and hide it', () => {
let luna;
beforeEach(async () => {
luna = await createUserAsync('luna', 'pw');
luna.post = await createAndReturnPost(luna, 'Luna post');
await hidePost(luna.post.id, luna);
});
it('should return post to Luna with truthy isHidden property', async () => {
const { posts } = await fetchPost(luna.post.id, luna);
expect(posts, 'to have key', 'isHidden'); // it is true because of schema
});
});
});
});
const postOpenGraphFetcher = (app) => async (postId) => {
const res = await fetch(`${app.context.config.host}/v2/posts-opengraph/${postId}`);
if (res.status !== 200) {
expect.fail('HTTP error (code {0})', res.status);
}
return await res.text();
};