Skip to content

Commit a063a34

Browse files
authored
Merge pull request #761 from topcoder-platform/CORE-100
Core 100
2 parents 4829821 + 36ddc78 commit a063a34

File tree

4 files changed

+858
-1
lines changed

4 files changed

+858
-1
lines changed

src/routes/attachments/create.spec.js

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
/* eslint-disable no-unused-expressions */
2+
import chai from 'chai';
3+
import sinon from 'sinon';
4+
import _ from 'lodash';
5+
import request from 'supertest';
6+
import server from '../../app';
7+
import models from '../../models';
8+
import util from '../../util';
9+
import fileService from '../../services/fileService';
10+
import testUtil from '../../tests/util';
11+
import busApi from '../../services/busApi';
12+
import { BUS_API_EVENT, RESOURCES, CONNECT_NOTIFICATION_EVENT, ATTACHMENT_TYPES } from '../../constants';
13+
14+
const should = chai.should();
15+
16+
const fileAttachmentBody = {
17+
title: 'Spec.pdf',
18+
description: 'attachment file description',
19+
category: 'appDefinition',
20+
path: 'projects/1/spec.pdf',
21+
type: ATTACHMENT_TYPES.FILE,
22+
tags: ['tag1', 'tag2', 'tag3'],
23+
s3Bucket: 'submissions-staging-dev',
24+
contentType: 'application/pdf',
25+
};
26+
27+
const linkAttachmentBody = {
28+
title: 'link title',
29+
description: 'link description',
30+
category: 'appDefinition',
31+
path: 'https://connect.topcoder-dev.com/projects/8600/assets',
32+
type: ATTACHMENT_TYPES.LINK,
33+
tags: ['tag4', 'tag5'],
34+
};
35+
36+
describe('Project Attachments', () => {
37+
let project1;
38+
let stub;
39+
let sandbox;
40+
41+
beforeEach((done) => {
42+
// mocks
43+
testUtil.clearDb()
44+
.then(() => {
45+
models.Project.create({
46+
type: 'generic',
47+
billingAccountId: 1,
48+
name: 'test1',
49+
description: 'test project1',
50+
status: 'draft',
51+
details: {},
52+
createdBy: 1,
53+
updatedBy: 1,
54+
lastActivityAt: 1,
55+
lastActivityUserId: '1',
56+
}).then((p) => {
57+
project1 = p;
58+
// create members
59+
models.ProjectMember.create({
60+
userId: 40051332,
61+
projectId: project1.id,
62+
role: 'copilot',
63+
isPrimary: true,
64+
createdBy: 1,
65+
updatedBy: 1,
66+
}).then(() => {
67+
sandbox = sinon.sandbox.create();
68+
stub = sandbox.stub(
69+
fileService,
70+
'getDownloadUrl',
71+
() => 'http://topcoder-media.s3.amazon.com/projects/1/spec.pdf',
72+
);
73+
sandbox.stub(util, 's3FileTransfer').returns(Promise.resolve(true));
74+
done();
75+
});
76+
});
77+
});
78+
});
79+
80+
afterEach((done) => {
81+
sandbox.restore();
82+
testUtil.clearDb(done);
83+
});
84+
85+
describe('POST /projects/{id}/attachments/', () => {
86+
it('should return 403 if user does not have permissions', (done) => {
87+
request(server)
88+
.post(`/v5/projects/${project1.id}/attachments/`)
89+
.set({
90+
Authorization: `Bearer ${testUtil.jwts.member}`,
91+
})
92+
.send(fileAttachmentBody)
93+
.expect('Content-Type', /json/)
94+
.expect(403, done);
95+
});
96+
97+
it('should return 400 if contentType is not provided for file attachment', (done) => {
98+
const payload = _.omit(_.cloneDeep(fileAttachmentBody), 'contentType');
99+
request(server)
100+
.post(`/v5/projects/${project1.id}/attachments/`)
101+
.set({
102+
Authorization: `Bearer ${testUtil.jwts.copilot}`,
103+
})
104+
.send(payload)
105+
.expect('Content-Type', /json/)
106+
.expect(400, done);
107+
});
108+
109+
it('should return 400 if s3Bucket is not provided for file attachment', (done) => {
110+
const payload = _.omit(_.cloneDeep(fileAttachmentBody), 's3Bucket');
111+
request(server)
112+
.post(`/v5/projects/${project1.id}/attachments/`)
113+
.set({
114+
Authorization: `Bearer ${testUtil.jwts.copilot}`,
115+
})
116+
.send(payload)
117+
.expect('Content-Type', /json/)
118+
.expect(400, done);
119+
});
120+
121+
it('should properly create file attachment - 201', (done) => {
122+
request(server)
123+
.post(`/v5/projects/${project1.id}/attachments/`)
124+
.set({
125+
Authorization: `Bearer ${testUtil.jwts.copilot}`,
126+
})
127+
.send(fileAttachmentBody)
128+
.expect('Content-Type', /json/)
129+
.expect(201)
130+
.end((err, res) => {
131+
if (err) {
132+
done(err);
133+
} else {
134+
const resJson = res.body;
135+
should.exist(resJson);
136+
stub.restore();
137+
resJson.title.should.equal(fileAttachmentBody.title);
138+
resJson.tags.should.eql(fileAttachmentBody.tags);
139+
resJson.type.should.eql(fileAttachmentBody.type);
140+
resJson.downloadUrl.should.exist;
141+
resJson.projectId.should.equal(project1.id);
142+
done();
143+
}
144+
});
145+
});
146+
147+
it('should properly create link attachment - 201', (done) => {
148+
request(server)
149+
.post(`/v5/projects/${project1.id}/attachments/`)
150+
.set({
151+
Authorization: `Bearer ${testUtil.jwts.copilot}`,
152+
})
153+
.send(linkAttachmentBody)
154+
.expect('Content-Type', /json/)
155+
.expect(201)
156+
.end((err, res) => {
157+
if (err) {
158+
done(err);
159+
} else {
160+
const resJson = res.body;
161+
should.exist(resJson);
162+
stub.restore();
163+
resJson.title.should.equal(linkAttachmentBody.title);
164+
resJson.path.should.equal(linkAttachmentBody.path);
165+
resJson.description.should.equal(linkAttachmentBody.description);
166+
resJson.type.should.equal(linkAttachmentBody.type);
167+
resJson.tags.should.eql(linkAttachmentBody.tags);
168+
resJson.projectId.should.equal(project1.id);
169+
done();
170+
}
171+
});
172+
});
173+
174+
it('should create project successfully using M2M token with "write:projects" scope', (done) => {
175+
request(server)
176+
.post(`/v5/projects/${project1.id}/attachments/`)
177+
.set({
178+
Authorization: `Bearer ${testUtil.m2m['write:projects']}`,
179+
})
180+
.send(fileAttachmentBody)
181+
.expect('Content-Type', /json/)
182+
.expect(201)
183+
.end((err, res) => {
184+
if (err) {
185+
done(err);
186+
} else {
187+
const resJson = res.body;
188+
should.exist(resJson);
189+
stub.restore();
190+
resJson.title.should.equal(fileAttachmentBody.title);
191+
resJson.tags.should.eql(fileAttachmentBody.tags);
192+
resJson.type.should.eql(fileAttachmentBody.type);
193+
resJson.downloadUrl.should.exist;
194+
resJson.projectId.should.equal(project1.id);
195+
done();
196+
}
197+
});
198+
});
199+
200+
describe('Bus api', () => {
201+
let createEventSpy;
202+
203+
before((done) => {
204+
// Wait for 500ms in order to wait for createEvent calls from previous tests to complete
205+
testUtil.wait(done);
206+
});
207+
208+
beforeEach(() => {
209+
createEventSpy = sandbox.spy(busApi, 'createEvent');
210+
});
211+
212+
it('should send correct BUS API messages when file attachment added', (done) => {
213+
request(server)
214+
.post(`/v5/projects/${project1.id}/attachments/`)
215+
.set({
216+
Authorization: `Bearer ${testUtil.jwts.admin}`,
217+
})
218+
.send(fileAttachmentBody)
219+
.expect(201)
220+
.end((err) => {
221+
if (err) {
222+
done(err);
223+
} else {
224+
// Wait for app message handler to complete
225+
testUtil.wait(() => {
226+
createEventSpy.calledThrice.should.be.true;
227+
228+
createEventSpy.calledWith(BUS_API_EVENT.PROJECT_ATTACHMENT_ADDED, sinon.match({
229+
resource: RESOURCES.ATTACHMENT,
230+
title: fileAttachmentBody.title,
231+
description: fileAttachmentBody.description,
232+
category: fileAttachmentBody.category,
233+
contentType: fileAttachmentBody.contentType,
234+
type: fileAttachmentBody.type,
235+
tags: fileAttachmentBody.tags,
236+
})).should.be.true;
237+
238+
// Check Notification Service events
239+
createEventSpy.calledWith(CONNECT_NOTIFICATION_EVENT.PROJECT_FILE_UPLOADED)
240+
.should.be.true;
241+
createEventSpy.calledWith(CONNECT_NOTIFICATION_EVENT.PROJECT_ATTACHMENT_UPDATED, sinon.match({
242+
projectId: project1.id,
243+
projectName: project1.name,
244+
projectUrl: `https://local.topcoder-dev.com/projects/${project1.id}`,
245+
userId: 40051333,
246+
initiatorUserId: 40051333,
247+
})).should.be.true;
248+
249+
done();
250+
});
251+
}
252+
});
253+
});
254+
255+
it('should send correct BUS API messages when link attachment added', (done) => {
256+
request(server)
257+
.post(`/v5/projects/${project1.id}/attachments/`)
258+
.set({
259+
Authorization: `Bearer ${testUtil.jwts.admin}`,
260+
})
261+
.send(linkAttachmentBody)
262+
.expect(201)
263+
.end((err) => {
264+
if (err) {
265+
done(err);
266+
} else {
267+
// Wait for app message handler to complete
268+
testUtil.wait(() => {
269+
createEventSpy.calledThrice.should.be.true;
270+
271+
createEventSpy.calledWith(BUS_API_EVENT.PROJECT_ATTACHMENT_ADDED, sinon.match({
272+
resource: RESOURCES.ATTACHMENT,
273+
title: linkAttachmentBody.title,
274+
description: linkAttachmentBody.description,
275+
category: linkAttachmentBody.category,
276+
type: linkAttachmentBody.type,
277+
path: linkAttachmentBody.path,
278+
tags: linkAttachmentBody.tags,
279+
})).should.be.true;
280+
281+
// Check Notification Service events
282+
createEventSpy.calledWith(CONNECT_NOTIFICATION_EVENT.PROJECT_LINK_CREATED)
283+
.should.be.true;
284+
createEventSpy.calledWith(CONNECT_NOTIFICATION_EVENT.PROJECT_ATTACHMENT_UPDATED, sinon.match({
285+
projectId: project1.id,
286+
projectName: project1.name,
287+
projectUrl: `https://local.topcoder-dev.com/projects/${project1.id}`,
288+
userId: 40051333,
289+
initiatorUserId: 40051333,
290+
})).should.be.true;
291+
292+
done();
293+
});
294+
}
295+
});
296+
});
297+
});
298+
});
299+
});

0 commit comments

Comments
 (0)