Skip to content

Commit

Permalink
feat(general): body campaigns added + testing
Browse files Browse the repository at this point in the history
  • Loading branch information
serge1peshcoff committed Feb 26, 2020
1 parent ee8685f commit 3a4ed73
Show file tree
Hide file tree
Showing 12 changed files with 527 additions and 8 deletions.
11 changes: 11 additions & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const circles = require('../middlewares/circles');
const permissions = require('../middlewares/permissions');
const memberships = require('../middlewares/memberships');
const joinRequests = require('../middlewares/join-requests');
const bodyCampaigns = require('../middlewares/body-campaigns');

const GeneralRouter = router({ mergeParams: true });
const MemberRouter = router({ mergeParams: true });
Expand All @@ -32,6 +33,7 @@ const JoinRequestsRouter = router({ mergeParams: true });
const CirclesRouter = router({ mergeParams: true });
const PermissionsRouter = router({ mergeParams: true });
const CampaignsRouter = router({ mergeParams: true });
const BodyCampaignsRouter = router({ mergeParams: true });

const server = express();
server.use(bodyParser.json());
Expand Down Expand Up @@ -83,6 +85,8 @@ MemberRouter.put('/', members.updateUser);
BodiesRouter.use(fetch.fetchBody);
BodiesRouter.get('/', bodies.getBody);
BodiesRouter.use(middlewares.maybeAuthorize, middlewares.ensureAuthorized);
BodiesRouter.get('/campaigns', bodyCampaigns.listAllCampaigns);
BodiesRouter.post('/campaigns', bodyCampaigns.createCampaign);
BodiesRouter.get('/members', memberships.listAllMemberships);
BodiesRouter.get('/join-requests', joinRequests.listAllJoinRequests);
BodiesRouter.post('/join-requests', joinRequests.createJoinRequest);
Expand Down Expand Up @@ -117,9 +121,16 @@ CampaignsRouter.get('/', campaigns.getCampaign);
CampaignsRouter.put('/', campaigns.updateCampaign);
CampaignsRouter.delete('/', campaigns.deleteCampaign);

// Everything related to a specific body campaign. Auth only.
BodyCampaignsRouter.use(middlewares.maybeAuthorize, middlewares.ensureAuthorized, fetch.fetchBody, fetch.fetchBodyCampaign);
BodyCampaignsRouter.get('/', bodyCampaigns.getCampaign);
BodyCampaignsRouter.put('/', bodyCampaigns.updateCampaign);
BodyCampaignsRouter.delete('/', bodyCampaigns.deleteCampaign);

server.use('/members/:user_id', MemberRouter);
server.use('/bodies/:body_id/members/:membership_id', MembershipsRouter);
server.use('/bodies/:body_id/join-requests/:request_id', JoinRequestsRouter);
server.use('/bodies/:body_id/campaigns/:campaign_id', BodyCampaignsRouter);
server.use('/bodies/:body_id', BodiesRouter);
server.use('/circles/:circle_id', CirclesRouter);
server.use('/permissions/:permission_id', PermissionsRouter);
Expand Down
57 changes: 57 additions & 0 deletions middlewares/body-campaigns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { Campaign } = require('../models');
const helpers = require('../lib/helpers');

exports.listAllCampaigns = async (req, res) => {
const result = await Campaign.findAndCountAll({
where: { autojoin_body_id: req.currentBody.id },
...helpers.getPagination(req.query),
order: helpers.getSorting(req.query)
});

return res.json({
success: true,
data: result.rows,
meta: { count: result.count }
});
};

exports.getCampaign = async (req, res) => {
// TODO: check permissions
return res.json({
success: true,
data: req.currentBodyCampaign
});
};

exports.createCampaign = async (req, res) => {
// TODO: check permissions
// TODO: filter out fields that are changed in the other way
const circle = await Campaign.create({
...req.body,
body_id: req.currentBody.idd
});

return res.json({
success: true,
data: circle
});
};

exports.updateCampaign = async (req, res) => {
// TODO: check permissions
// TODO: filter out fields that are changed in the other way
await req.currentBodyCampaign.update(req.body);
return res.json({
success: true,
data: req.currentBodyCampaign
});
};

exports.deleteCampaign = async (req, res) => {
// TODO: check permissions
await req.currentBodyCampaign.destroy();
return res.json({
success: true,
message: 'Campaign is deleted.'
});
};
27 changes: 21 additions & 6 deletions middlewares/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ exports.fetchPermission = async (req, res, next) => {
}

req.currentPermission = permission;

// TODO: fetch permissions

return next();
};

Expand All @@ -120,9 +117,6 @@ exports.fetchCampaign = async (req, res, next) => {
}

req.currentCampaign = campaign;

// TODO: fetch permissions

return next();
};

Expand Down Expand Up @@ -165,3 +159,24 @@ exports.fetchJoinRequest = async (req, res, next) => {
req.currentJoinRequest = request;
return next();
};

exports.fetchBodyCampaign = async (req, res, next) => {
// searching the campaign by id if it's numeric
if (!helpers.isNumber(req.params.campaign_id)) {
return errors.makeBadRequestError(res, 'Campaign ID is invalid.');
}

const campaign = await Campaign.findOne({
where: {
id: Number(req.params.campaign_id),
autojoin_body_id: req.currentBody.id
}
});

if (!campaign) {
return errors.makeNotFoundError(res, 'Campaign is not found.');
}

req.currentBodyCampaign = campaign;
return next();
};
16 changes: 16 additions & 0 deletions migrations/20200226170830-add-autojoin-body-id-to-campaigns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.addColumn(
'campaigns',
'autojoin_body_id',
{
type: Sequelize.INTEGER,
allowNull: true,
references: {
model: 'bodies',
key: 'id'
},
onDelete: 'SET NULL'
},
),
down: (queryInterface) => queryInterface.removeColumn('campaigns', 'autojoin_body_id')
};
2 changes: 1 addition & 1 deletion models/Campaign.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Campaign = sequelize.define('campaign', {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: true
},
}
}, {
underscored: true,
tableName: 'campaigns',
Expand Down
3 changes: 3 additions & 0 deletions models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const JoinRequest = require('./JoinRequest');
Campaign.hasMany(User, { foreignKey: 'campaign_id' });
User.belongsTo(Campaign, { foreignKey: 'campaign_id' });

Body.hasOne(Campaign, { foreignKey: 'autojoin_body_id', as: 'autojoin_body' });
Campaign.belongsTo(Body, { foreignKey: 'autojoin_body_id', as: 'autojoin_body' });

User.hasMany(MailConfirmation, { foreignKey: 'user_id' });
MailConfirmation.belongsTo(User, { foreignKey: 'user_id' });

Expand Down
80 changes: 80 additions & 0 deletions test/api/body-campaigns-creating.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const { startServer, stopServer } = require('../../lib/server.js');
const { request } = require('../scripts/helpers');
const generator = require('../scripts/generator');

describe('Campaigns creating', () => {
beforeAll(async () => {
await startServer();
});

afterAll(async () => {
await stopServer();
});

afterEach(async () => {
await generator.clearAll();
});

test('should fail if there are validation errors', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = generator.generateCampaign({ name: '' });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns',
method: 'POST',
headers: { 'X-Auth-Token': token.value },
body: campaign
});

expect(res.statusCode).toEqual(422);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('errors');
expect(res.body.errors).toHaveProperty('name');
});

test('should succeed if everything is okay', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = generator.generateCampaign();

const res = await request({
uri: '/bodies/' + body.id + '/campaigns',
method: 'POST',
headers: { 'X-Auth-Token': token.value },
body: campaign
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('data');
expect(res.body.data.name).toEqual(campaign.name);
});

test('should override body id', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = generator.generateCampaign({ body_id: 1337 });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns',
method: 'POST',
headers: { 'X-Auth-Token': token.value },
body: campaign
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('data');
expect(res.body.data.body_id).not.toEqual(1337);
});
});
77 changes: 77 additions & 0 deletions test/api/body-campaigns-deleting.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const { startServer, stopServer } = require('../../lib/server.js');
const { request } = require('../scripts/helpers');
const generator = require('../scripts/generator');
const { Campaign } = require('../../models');

describe('Body campaigns deleting', () => {
beforeAll(async () => {
await startServer();
});

afterAll(async () => {
await stopServer();
});

afterEach(async () => {
await generator.clearAll();
});

test('should return 404 if the campaign is not found', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/1337',
method: 'DELETE',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(404);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});

test('should fail for other body\'s campaign', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();
const otherBody = await generator.createBody();

const campaign = await generator.createCampaign({ autojoin_body_id: otherBody.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'DELETE',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(404);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});

test('should succeed if everything is okay', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'DELETE',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('message');

const campaignFromDb = await Campaign.findByPk(campaign.id);
expect(campaignFromDb).toEqual(null);
});
});
Loading

0 comments on commit 3a4ed73

Please sign in to comment.