Skip to content

Commit

Permalink
feat(general): trimming values and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
serge1peshcoff committed Feb 11, 2020
1 parent f3e0f62 commit 8bf7a22
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 16 deletions.
6 changes: 6 additions & 0 deletions models/BodyMembership.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ const BodyMembership = sequelize.define('body_membership', {
updatedAt: 'updated_at',
});


BodyMembership.beforeValidate(async (membership) => {
// skipping these fields if they are unset, will catch it later.
if (typeof membership.comment === 'string') membership.comment = membership.comment.trim();
});

module.exports = BodyMembership;
19 changes: 14 additions & 5 deletions models/Campaign.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ const Campaign = sequelize.define('campaign', {
name: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Name should be set.' },
notNull: { msg: 'Name should be set.' }
}
},
url: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Name should be set.' },
notEmpty: { msg: 'URL should be set.' },
notNull: { msg: 'URL should be set.' }
},
unique: true
},
Expand All @@ -26,17 +26,17 @@ const Campaign = sequelize.define('campaign', {
description_short: {
type: Sequelize.TEXT,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Description should be set.' },
notNull: { msg: 'Description should be set.' }
}
},
description_long: {
type: Sequelize.TEXT,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Description should be set.' },
notNull: { msg: 'Description should be set.' }
}
},
activate_user: {
Expand All @@ -51,4 +51,13 @@ const Campaign = sequelize.define('campaign', {
updatedAt: 'updated_at',
});

Campaign.beforeValidate(async (campaign) => {
// skipping these fields if they are unset, will catch it later.
if (typeof campaign.name === 'string') campaign.name = campaign.name.trim();
if (typeof campaign.url === 'string') campaign.url = campaign.url.toLowerCase().trim();
if (typeof campaign.description_short === 'string') campaign.description_short = campaign.description_short.trim();
if (typeof campaign.description_long === 'string') campaign.description_long = campaign.description_long.trim();
});


module.exports = Campaign;
6 changes: 6 additions & 0 deletions models/Circle.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ const Circle = sequelize.define('circle', {
updatedAt: 'updated_at',
});

Circle.beforeValidate(async (circle) => {
// skipping these fields if they are unset, will catch it later.
if (typeof circle.name === 'string') circle.name = circle.name.trim();
if (typeof circle.description === 'string') circle.description = circle.description.trim();
});

// Checking if there isn't a loop inside circles (so no circle1 -> circle2 -> circle1).
Circle.throwIfAnyLoops = async function throwIfAnyLoops(transaction) {
// Firstly, loading all bound circles.
Expand Down
9 changes: 5 additions & 4 deletions models/Permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const Permission = sequelize.define('permission', {
scope: {
type: Sequelize.ENUM('global', 'global'),
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Scope should be set.' },
isIn: {
args: [['global', 'local']],
msg: 'Permission scope should be one of these: "global", "local".'
Expand All @@ -16,18 +16,18 @@ const Permission = sequelize.define('permission', {
action: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Action should be set.' },
notNull: { msg: 'Action should be set.' }
},
unique: { args: true, msg: 'There\'s already a permission with such scope, action and object.' }
},
object: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Object should be set.' },
notNull: { msg: 'Object should be set.' }
},
unique: { args: true, msg: 'There\'s already a permission with such scope, action and object.' }
},
Expand All @@ -38,9 +38,9 @@ const Permission = sequelize.define('permission', {
description: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Description should be set.' },
notNull: { msg: 'Description should be set.' }
},
},
filters: {
Expand All @@ -59,6 +59,7 @@ Permission.beforeValidate(async (permission) => {
// skipping these fields if they are unset, will catch it later.
if (typeof permission.action === 'string') permission.action = permission.action.toLowerCase().trim();
if (typeof permission.object === 'string') permission.object = permission.object.toLowerCase().trim();
if (typeof permission.description === 'string') permission.description = permission.description.trim();
});

Permission.afterValidate((permission) => {
Expand Down
21 changes: 14 additions & 7 deletions models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const User = sequelize.define('user', {
username: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Username should be set.' },
notNull: { msg: 'Username should be set.' },
isValid(value) {
if (!/^[a-zA-Z0-9._-]*$/.test(value)) {
throw new Error('Username should only contain letters, numbers, dots, underscores and dashes.');
Expand All @@ -21,18 +21,18 @@ const User = sequelize.define('user', {
email: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Email should be set.' },
notNull: { msg: 'Email should be set.' },
isEmail: { msg: 'Email should be valid.' }
},
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notNull: { msg: 'Password should be set.' },
notEmpty: { msg: 'Password should be set.' },
}
},
Expand All @@ -56,25 +56,25 @@ const User = sequelize.define('user', {
first_name: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'First name should be set.' },
notNull: { msg: 'First name should be set.' },
isValid(value) {
if (!new RegExp('^[\\p{L} -]*$', 'u').test(value)) {
throw new Error('First name should only contain letters, spaces and dashes.');
throw new Error(`First name should only contain letters, spaces and dashes, got "${value}".`);
}
}
}
},
last_name: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Last name should be set.' },
notNull: { msg: 'Last name should be set.' },
isValid(value) {
if (!new RegExp('^[\\p{L} -\']*$', 'u').test(value)) {
throw new Error('Last name should only contain letters, spaces and dashes.');
throw new Error(`Last name should only contain letters, spaces and dashes, got "${value}".`);
}
}
}
Expand Down Expand Up @@ -125,6 +125,13 @@ User.beforeValidate(async (user) => {
// skipping these fields if they are unset, will catch it later.
if (typeof user.email === 'string') user.email = user.email.toLowerCase().trim();
if (typeof user.username === 'string') user.username = user.username.toLowerCase().trim();

if (typeof user.first_name === 'string') user.first_name = user.first_name.trim();
if (typeof user.last_name === 'string') user.last_name = user.last_name.trim();
if (typeof user.gender === 'string') user.gender = user.gender.trim();
if (typeof user.phone === 'string') user.phone = user.phone.trim();
if (typeof user.address === 'string') user.address = user.address.trim();
if (typeof user.about_me === 'string') user.about_me = user.about_me.trim();
});

User.afterValidate(async (user) => {
Expand Down
109 changes: 109 additions & 0 deletions test/api/my-permissions-body.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const { startServer, stopServer } = require('../../lib/server.js');
const { request } = require('../scripts/helpers');
const generator = require('../scripts/generator');

describe('My permissions body', () => {
beforeAll(async () => {
await startServer();
});

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

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

test('should list the global permission that is assigned to a circle user is member of', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const permission = await generator.createPermission({ scope: 'global', action: 'action', object: 'object' });
const circle = await generator.createCircle();
await generator.createCirclePermission(circle, permission);
await generator.createCircleMembership(circle, user);

const res = await request({
uri: '/my_permissions',
method: 'GET',
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('data');
expect(res.body.data.length).toEqual(1);
expect(res.body.data[0].combined).toEqual('global:action:object');
});

test('should not list the local permissions that is assigned to a circle user is member of', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const permission = await generator.createPermission({ scope: 'local', action: 'action', object: 'object' });
const circle = await generator.createCircle();
await generator.createCirclePermission(circle, permission);
await generator.createCircleMembership(circle, user);

const res = await request({
uri: '/my_permissions',
method: 'GET',
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('data');
expect(res.body.data.length).toEqual(0);
});

test('should list the global permission that is assigned to a circle user is indirectly a member of', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const permission = await generator.createPermission({ scope: 'global', action: 'action', object: 'object' });
const firstCircle = await generator.createCircle();
const secondCircle = await generator.createCircle({ parent_circle_id: firstCircle.id });
const thirdCircle = await generator.createCircle({ parent_circle_id: secondCircle.id });

await generator.createCirclePermission(firstCircle, permission);
await generator.createCircleMembership(thirdCircle, user);

const res = await request({
uri: '/my_permissions',
method: 'GET',
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('data');
expect(res.body.data.length).toEqual(1);
expect(res.body.data[0].combined).toEqual('global:action:object');
});

test('should not list the global permission that is assigned to a circle user is not a member of', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const permission = await generator.createPermission({ scope: 'global', action: 'action', object: 'object' });
const circle = await generator.createCircle();
await generator.createCirclePermission(circle, permission);

const res = await request({
uri: '/my_permissions',
method: 'GET',
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('data');
expect(res.body.data.length).toEqual(0);
});
});
72 changes: 72 additions & 0 deletions test/unit/bodies.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const { startServer, stopServer } = require('../../lib/server.js');
const generator = require('../scripts/generator');
const { Body } = require('../../models');

describe('Bodies testing', () => {
beforeAll(async () => {
await startServer();
});

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

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

test('should fail with invalid email', async () => {
try {
await generator.createBody({ email: 'not-valid' });
expect(1).toEqual(0);
} catch (err) {
expect(err).toHaveProperty('errors');
expect(err.errors.length).toEqual(1);
expect(err.errors[0].path).toEqual('email');
}
});

test('should fail with null body_code', async () => {
try {
await generator.createBody({ code: null });
expect(1).toEqual(0);
} catch (err) {
expect(err).toHaveProperty('errors');
expect(err.errors.length).toEqual(1);
expect(err.errors[0].path).toEqual('code');
}
});

test('should fail with not set body_code', async () => {
try {
const body = generator.generateBody();
delete body.code;

await Body.create(body);

expect(1).toEqual(0);
} catch (err) {
expect(err).toHaveProperty('errors');
expect(err.errors.length).toEqual(1);
expect(err.errors[0].path).toEqual('code');
}
});

test('should work with email not set', async () => {
const data = generator.generateBody({ email: null });
const body = await Body.create(data);

expect(body.email).toEqual(null);
});

test('should normalize fields', async () => {
const data = generator.generateBody({
code: '\t\t\ttest\t\t\t',
email: ' \t test@TeSt.Io\t \t',
});

const body = await Body.create(data);
expect(body.code).toEqual('TEST');
expect(body.email).toEqual('test@test.io');
});
});
Loading

0 comments on commit 8bf7a22

Please sign in to comment.