WIP pass the failed tests.

This commit is contained in:
Ahmed Bouhuolia
2020-05-17 07:08:12 +02:00
parent 00de156c9f
commit 10f636d2bc
77 changed files with 2164 additions and 1403 deletions

37
server/tests/dbInit.js Normal file
View File

@@ -0,0 +1,37 @@
import {
request,
expect,
createTenantFactory,
createTenant,
bindTenantModel,
login,
systemFactory,
dropTenant,
} from '~/testInit';
let tenantWebsite;
let tenantFactory;
let loginRes;
beforeEach(async () => {
tenantWebsite = await createTenant();
tenantFactory = createTenantFactory(tenantWebsite.tenantDb);
bindTenantModel(tenantWebsite.tenantDb);
loginRes = await login(tenantWebsite);
});
afterEach(async () => {
await dropTenant(tenantWebsite);
loginRes = null;
tenantFactory = null;
tenantWebsite = null;
});
export {
tenantWebsite,
tenantFactory,
systemFactory,
loginRes,
};

View File

@@ -1,4 +1,4 @@
on: '2'
services:
mysql:
image: mysql/mysql-server:5.7
@@ -9,3 +9,6 @@ services:
- MYSQL_DATABASE=moosher_test
- MYSQL_USER=moosher
- MYSQL_PASSWORD=moosher
tmpfs:
- /var/lib/mysql/:rw,noexec,nosuid,size=600m
- /tmp/:rw,noexec,nosuid,size=50m

View File

@@ -1,12 +0,0 @@
import { expect } from '~/testInit';
import { Lexer } from '@/lib/LogicEvaluation/Lexer';
describe('Lexer', () => {
it('Should retrieve tokens of the expression.', () => {
const lexer = new Lexer('(1 && 2) || (2 || 3)');
const tokens = lexer.getTokens();
expect(tokens.length).equals(11);
});
});

View File

@@ -1,5 +0,0 @@
describe('MetableModel', () => {
});

View File

@@ -1,159 +0,0 @@
import Option from '@/models/Option';
import MetadataCollection from '@/lib/Metable/MetableCollection';
import ResourceFieldMetadata from '@/models/ResourceFieldMetadata';
import { create, expect } from '~/testInit';
describe('MetableCollection', () => {
describe('findMeta', () => {
it('Should retrieve the found meta object.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
const foundMeta = metadataCollection.findMeta(option.key);
expect(foundMeta).to.be.an('object');
});
it('Should retrieve the found meta with extra columns.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
const foundMeta = metadataCollection.findMeta({
key: option.key,
group: option.group,
});
expect(foundMeta).to.be.an('object');
});
});
describe('allMetadata', () => {
it('Should retrieve all exists metadata entries.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
const foundMetadata = metadataCollection.allMetadata();
expect(foundMetadata.length).equals(1);
});
});
describe('getMeta', () => {
it('Should retrieve the found meta value.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
const foundMeta = metadataCollection.getMeta(option.key);
expect(foundMeta).equals(option.value);
});
it('Should retrieve the default meta value in case the meta key was not exist.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
const foundMeta = metadataCollection.getMeta('not-found', true);
expect(foundMeta).equals(true);
});
});
describe('setMeta', () => {
it('Should sets the meta value to the stack.', async () => {
const metadataCollection = new MetadataCollection();
metadataCollection.setMeta('key', 'value');
expect(metadataCollection.metadata.length).equals(1);
});
it('Should sets the meta value with extra columns', async () => {
const metadataCollection = new MetadataCollection();
metadataCollection.setMeta({
key: 'key',
value: 'value',
group: 'group-1',
});
expect(metadataCollection.metadata.length).equals(1);
expect(metadataCollection.metadata[0].key).equals('key');
expect(metadataCollection.metadata[0].value).equals('value');
expect(metadataCollection.metadata[0].group).equals('group-1');
});
});
describe('removeAllMeta()', () => {
it('Should remove all metadata from the stack.', async () => {
const metadataCollection = new MetadataCollection();
metadataCollection.setModel(Option);
metadataCollection.setMeta('key', 'value');
metadataCollection.setMeta('key2', 'value2');
metadataCollection.removeAllMeta();
expect(metadataCollection.metadata.length).equals(2);
expect(metadataCollection.allMetadata().length).equals(0);
});
});
describe('saveMeta', () => {
it('Should save inserted new metadata.', async () => {
const metadataCollection = new MetadataCollection();
metadataCollection.setModel(Option);
metadataCollection.setMeta('key', 'value');
metadataCollection.setModel(Option);
await metadataCollection.saveMeta();
const storedMetadata = await Option.query();
expect(storedMetadata.metadata.length).equals(1);
});
it('Should save updated the exist metadata.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
metadataCollection.setModel(Option);
metadataCollection.setMeta(option.key, 'value');
metadataCollection.setModel(Option);
await metadataCollection.saveMeta();
const storedMetadata = await Option.query().where('key', option.key);
expect(storedMetadata.metadata[0].value).equals('value');
expect(storedMetadata.metadata[0].key).equals(option.key);
expect(storedMetadata.metadata[0].group).equals(option.group);
});
it('Should delete the removed metadata from storage.', async () => {
const option = await create('option');
const metadataCollection = await Option.query();
metadataCollection.removeMeta(option.key);
expect(metadataCollection.metadata.length).equals(1);
await metadataCollection.saveMeta();
const storedMetadata = await Option.query();
expect(storedMetadata.metadata.length).equals(0);
});
it('Should save instered new metadata with extra columns.', async () => {
const resource = await create('resource');
const metadataCollection = new MetadataCollection();
metadataCollection.extraColumns = ['resource_id'];
metadataCollection.setModel(ResourceFieldMetadata);
metadataCollection.setMeta({
key: 'key',
value: 'value',
resource_id: resource.id,
});
await metadataCollection.saveMeta();
const storedMetadata = await ResourceFieldMetadata.query().first();
expect(storedMetadata.metadata.length).equals(1);
expect(storedMetadata.metadata[0].resourceId).equals(resource.id);
});
});
});

View File

@@ -1,50 +0,0 @@
import { expect } from '~/testInit';
import { Lexer } from '@/lib/LogicEvaluation/Lexer';
import Parser from '@/lib/LogicEvaluation/Parser';
import QueryParser from '@/lib/LogicEvaluation/QueryParser';
import Expense from '@/models/Expense';
import knex from '@/database/knex';
describe('LoginEvaluation: Parser', () => {
it('Should parse the logic', async () => {
const lexer = new Lexer('(1 OR 2) AND (1 AND 3)');
const tokens = lexer.getTokens();
const parser = new Parser(tokens);
const parsedTree = parser.parse();
const queries = {
1: (query) => {
query.where('expense_account_id', 1);
},
2: (query) => {
query.where('payment_account_id', 2);
},
3: (query) => {
query.where('amount', '<', 100);
},
};
const queryParser = new QueryParser(parsedTree, queries);
const parsedQuery = queryParser.parse();
const parsedQueryWrapper = (builder) => {
parsedQuery(builder);
console.log(builder.toString());
};
const query = await knex.select('*').from('expenses')
.modify(parsedQueryWrapper);
// console.log(query);
// });
// console.log(a);
});
});

View File

@@ -1,125 +0,0 @@
import {
expect,
create,
login,
} from '~/testInit';
import Expense from '@/models/Expense';
import ResourceCustomFieldRepository from '@/services/CustomFields/ResourceCustomFieldRepository';
import ResourceFieldMetadata from '@/models/ResourceFieldMetadata';
let loginRes;
describe('ResourceCustomFieldRepository', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('constructor()', () => {
it('Should take the resource name from model class name', () => {
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
expect(customFieldsRepo.resourceName).equals('Expense');
});
});
describe('loadResource()', () => {
it('Should fetches the resource name.', async () => {
const resource = await create('resource', { name: 'Expense' });
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
await customFieldsRepo.loadResource();
expect(customFieldsRepo.resource.name).equals('Expense');
});
});
describe('loadResourceCustomFields()', () => {
it('Should fetches all custom fields that associated with the resource.', async () => {
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', { resource_id: resource.id });
const resourceField2 = await create('resource_field', { resource_id: resource.id });
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
await customFieldsRepo.loadResource();
await customFieldsRepo.loadResourceCustomFields();
expect(customFieldsRepo.customFields.length).equals(2);
});
});
describe('fetchCustomFieldsMetadata', () => {
it('Should fetches all custom fields metadata that associated to the resource and resource item.', async () => {
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', { resource_id: resource.id });
const resourceField2 = await create('resource_field', { resource_id: resource.id });
const expense = await create('expense');
const fieldMetadata = await create('resource_custom_field_metadata', {
resource_id: resource.id, resource_item_id: expense.id,
});
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
await customFieldsRepo.load();
await customFieldsRepo.fetchCustomFieldsMetadata(expense.id);
expect(customFieldsRepo.metadata[expense.id].metadata.length).equals(1);
expect(customFieldsRepo.metadata[expense.id].metadata[0].key).equals(fieldMetadata.key);
expect(customFieldsRepo.metadata[expense.id].metadata[0].value).equals(fieldMetadata.value);
});
});
describe('fillCustomFields', () => {
it('Should fill custom fields metadata attributes to metadata object.', async () => {
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', { resource_id: resource.id });
const expense = await create('expense');
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
await customFieldsRepo.load();
await customFieldsRepo.fetchCustomFieldsMetadata(expense.id);
customFieldsRepo.fillCustomFields(expense.id, [
{
key: resourceField.key,
value: 'Hello World',
},
]);
expect(customFieldsRepo.fieldsMetadata[expense.id].metadata.length).equals(1);
expect(customFieldsRepo.filledCustomFields[expense.id].length).equals(1);
});
});
describe('saveCustomFields', () => {
it('Should save the given custom fields metadata to the resource item.', async () => {
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', { resource_id: resource.id });
const expense = await create('expense');
const fieldMetadata = await create('resource_custom_field_metadata', {
key: resourceField.slug,
resource_id: resource.id,
resource_item_id: expense.id,
});
const customFieldsRepo = new ResourceCustomFieldRepository(Expense);
await customFieldsRepo.load();
await customFieldsRepo.fetchCustomFieldsMetadata(expense.id);
customFieldsRepo.fillCustomFields(expense.id, [
{ key: resourceField.slug, value: 'Hello World' },
]);
await customFieldsRepo.saveCustomFields(expense.id);
const updateResourceFieldData = await ResourceFieldMetadata.query();
expect(updateResourceFieldData.metadata[0].value).equals('Hello World');
});
});
describe('validateExistCustomFields', () => {
});
});

View File

@@ -1,89 +0,0 @@
import {
create,
expect,
request,
login,
} from '~/testInit';
let loginRes;
describe('ViewRolesBuilder', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
it('Should not retrieve results when there is no match query from view roles.', async () => {
const expenseResource = await create('resource', { name: 'expenses' });
const expenseField = await create('resource_field', {
label_name: 'Expense Account',
column_key: 'expense_account',
data_type: 'integer',
resource_id: expenseResource.id,
active: true,
predefined: true,
});
const expenseView = await create('view', {
name: 'Expense View',
resource_id: expenseResource.id,
roles_logic_expression: '1',
});
const expenseViewRole = await create('view_role', {
view_id: expenseView.id,
index: 1,
field_id: expenseField.id,
value: '12',
comparator: 'equals',
});
const expenseAccount = await create('account', { id: 10 });
const expense = await create('expense', { expense_account_id: expenseAccount.id });
const res = await request()
.get('/api/expenses')
.set('x-access-token', loginRes.body.token)
.query({ custom_view_id: expenseView.id })
.send();
expect(res.status).equals(200);
expect(res.body.expenses.results.length).equals(0);
});
it('Should retrieve results that match custom view conditionals roles.', async () => {
const expenseResource = await create('resource', { name: 'expenses' });
const expenseField = await create('resource_field', {
label_name: 'Expense Account',
column_key: 'expense_account',
data_type: 'integer',
resource_id: expenseResource.id,
active: true,
predefined: true,
});
const expenseView = await create('view', {
name: 'Expense View',
resource_id: expenseResource.id,
roles_logic_expression: '1',
});
const expenseViewRole = await create('view_role', {
view_id: expenseView.id,
index: 1,
field_id: expenseField.id,
value: '10',
comparator: 'equals',
});
const expenseAccount = await create('account', { id: 10 });
const expense = await create('expense', { expense_account_id: expenseAccount.id });
const res = await request()
.get('/api/expenses')
.set('x-access-token', loginRes.body.token)
.query({ custom_view_id: expenseView.id })
.send();
expect(res.status).equals(200);
expect(res.body.expenses.results.length).equals(1);
});
});

View File

@@ -1,13 +1,20 @@
import { create, expect } from '~/testInit';
import {
expect,
} from '~/testInit';
import Account from '@/models/Account';
import AccountType from '@/models/AccountType';
import {
tenantFactory,
tenantWebsite
} from '~/dbInit';
describe('Model: Account', () => {
it('Should account model belongs to the associated account type model.', async () => {
const accountType = await create('account_type');
const account = await create('account', { account_type_id: accountType.id });
const accountType = await tenantFactory.create('account_type');
const account = await tenantFactory.create('account', { account_type_id: accountType.id });
const accountModel = await Account.query()
const accountModel = await Account.tenant().query()
.where('id', account.id)
.withGraphFetched('type')
.first();
@@ -16,9 +23,9 @@ describe('Model: Account', () => {
});
it('Should account model has one balance model that associated to the account model.', async () => {
const accountBalance = await create('account_balance');
const accountBalance = await tenantFactory.create('account_balance');
const accountModel = await Account.query()
const accountModel = await Account.tenant().query()
.where('id', accountBalance.accountId)
.withGraphFetched('balance')
.first();
@@ -27,10 +34,10 @@ describe('Model: Account', () => {
});
it('Should account model has many transactions models that associated to the account model.', async () => {
const account = await create('account');
const accountTransaction = await create('account_transaction', { account_id: account.id });
const account = await tenantFactory.create('account');
const accountTransaction = await tenantFactory.create('account_transaction', { account_id: account.id });
const accountModel = await Account.query().where('id', account.id).first();
const accountModel = await Account.tenant().query().where('id', account.id).first();
const transactionsModels = await accountModel.$relatedQuery('transactions');
expect(transactionsModels.length).equals(1);

View File

@@ -1,14 +1,20 @@
import { create, expect } from '~/testInit';
import '@/models/Account';
import AccountType from '@/models/AccountType';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: AccountType', () => {
it('Shoud account type model has many associated accounts.', async () => {
const accountType = await create('account_type');
await create('account', { account_type_id: accountType.id });
await create('account', { account_type_id: accountType.id });
const accountType = await tenantFactory.create('account_type');
await tenantFactory.create('account', { account_type_id: accountType.id });
await tenantFactory.create('account', { account_type_id: accountType.id });
const accountTypeModel = await AccountType.query().where('id', accountType.id).first();
const accountTypeModel = await AccountType.tenant().query().where('id', accountType.id).first();
const typeAccounts = await accountTypeModel.$relatedQuery('accounts');
expect(typeAccounts.length).equals(2);

View File

@@ -1,34 +0,0 @@
import { create, expect } from '~/testInit';
import Expense from '@/models/Expense';
import factory from '../../src/database/factories';
describe('Model: Expense', () => {
describe('relations', () => {
it('Expense model may belongs to associated payment account.', async () => {
const expense = await factory.create('expense');
const expenseModel = await Expense.query().findById(expense.id);
const paymentAccountModel = await expenseModel.$relatedQuery('paymentAccount');
expect(paymentAccountModel.id).equals(expense.paymentAccountId);
});
it('Expense model may belongs to associated expense account.', async () => {
const expense = await factory.create('expense');
const expenseModel = await Expense.query().findById(expense.id);
const expenseAccountModel = await expenseModel.$relatedQuery('expenseAccount');
expect(expenseAccountModel.id).equals(expense.expenseAccountId);
});
it('Expense model may belongs to associated user model.', async () => {
const expense = await factory.create('expense');
const expenseModel = await Expense.query().findById(expense.id);
const expenseUserModel = await expenseModel.$relatedQuery('user');
expect(expenseUserModel.id).equals(expense.userId);
});
});
});

View File

@@ -2,27 +2,21 @@ import { create, expect } from '~/testInit';
import Item from '@/models/Item';
// eslint-disable-next-line no-unused-vars
import itemCategory from '@/models/ItemCategory';
import '@/models/ItemMetadata';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: Item', () => {
it('Should item model belongs to the associated category model.', async () => {
const category = await create('item_category');
const item = await create('item', { category_id: category.id });
const category = await tenantFactory.create('item_category');
const item = await tenantFactory.create('item', { category_id: category.id });
const itemModel = await Item.query().where('id', item.id);
const itemModel = await Item.tenant().query().where('id', item.id).first();
const itemCategoryModel = await itemModel.$relatedQuery('category');
expect(itemCategoryModel.attributes.id).equals(category.id);
});
it('Should item model has many metadata that assciated to the item model.', async () => {
const item = await create('item');
await create('item_metadata', { item_id: item.id });
await create('item_metadata', { item_id: item.id });
const itemModel = await Item.query().where('id', item.id);
const itemMetadataCollection = await itemModel.$relatedQuery('metadata');
expect(itemMetadataCollection.length).equals(2);
expect(itemCategoryModel.id).equals(category.id);
});
});

View File

@@ -1,15 +1,23 @@
import { create, expect } from '~/testInit';
import '@/models/Item';
import ItemCategory from '@/models/ItemCategory';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: ItemCategories', () => {
it('Shoud item category model has many associated items.', async () => {
const category = await create('item_category');
await create('item', { category_id: category.id });
await create('item', { category_id: category.id });
const category = await tenantFactory.create('item_category');
await tenantFactory.create('item', { category_id: category.id });
await tenantFactory.create('item', { category_id: category.id });
const categoryModel = await ItemCategory.where('id', category.id).fetch();
const categoryItems = await categoryModel.items().fetch();
const categoryModel = await ItemCategory.tenant().query()
.where('id', category.id).first();
const categoryItems = await categoryModel.$relatedQuery('items');
expect(categoryItems.length).equals(2);
});

View File

@@ -1,12 +1,17 @@
import { create, expect } from '~/testInit';
import Option from '@/models/Option';
import MetableCollection from '@/lib/Metable/MetableCollection';
import {
tenantFactory,
tenantWebsite,
} from '~/dbInit';
describe('Model: Option', () => {
it('Should result collection be instance of `MetableCollection` class.', async () => {
await create('option');
await create('option');
const options = await Option.query();
await tenantFactory.create('option');
await tenantFactory.create('option');
const options = await Option.tenant().query();
expect(options).to.be.an.instanceof(MetableCollection);
});

View File

@@ -1,21 +0,0 @@
import { create } from '~/testInit';
import Resource from '@/models/Resource';
import '@/models/Role';
describe('Model: Permission', () => {
it('Permission model may has associated role.', async () => {
const roleHasPermissions = await create('role_has_permission');
const resourceModel = await Resource.where('id', roleHasPermissions.resource_id).fetch();
const roleModel = await resourceModel.role().fetch();
console.log(roleModel);
});
it('Permission model may has associated resource.', async () => {
const roleHasPermissions = await create('role_has_permission');
const resourceModel = await Resource.where('id', roleHasPermissions.resource_id).fetch();
const permissionModel = await resourceModel.permission().fetch();
console.log(permissionModel);
});
});

View File

@@ -2,22 +2,28 @@ import { create, expect } from '~/testInit';
import Resource from '@/models/Resource';
import '@/models/View';
import '@/models/ResourceField';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: Resource', () => {
it('Resource model may has many associated views.', async () => {
const view = await create('view');
await create('view', { resource_id: view.resourceId });
const view = await tenantFactory.create('view');
await tenantFactory.create('view', { resource_id: view.resourceId });
const resourceModel = await Resource.query().findById(view.resourceId);
const resourceModel = await Resource.tenant().query().findById(view.resourceId);
const resourceViews = await resourceModel.$relatedQuery('views');
expect(resourceViews).to.have.lengthOf(2);
});
it('Resource model may has many fields.', async () => {
const resourceField = await create('resource_field');
const resourceField = await tenantFactory.create('resource_field');
const resourceModel = await Resource.query().findById(resourceField.resourceId);
const resourceModel = await Resource.tenant().query().findById(resourceField.resourceId);
const resourceFields = await resourceModel.$relatedQuery('fields');
expect(resourceFields).to.have.lengthOf(1);

View File

@@ -1,18 +0,0 @@
import { create, expect } from '~/testInit';
import Resource from '@/models/Resource';
import ResourceField from '@/models/ResourceField';
import '@/models/View';
describe('Model: ResourceField', () => {
it('Resource field model may belongs to associated resource.', async () => {
const resourceField = await create('resource_field');
const resourceFieldModel = await ResourceField.where('id', resourceField.id).fetch();
const resourceModel = resourceFieldModel.resource().fetch();
const foundResource = await Resource.where('id', resourceField.resource_id).fetch();
expect(resourceModel.attributes.id).equals(foundResource.id);
expect(resourceModel.attributes.name).equals(foundResource.name);
});
});

View File

@@ -1,34 +0,0 @@
import { expect, create } from '~/testInit';
import Role from '@/models/Role';
import '@/models/Permission';
import '@/models/Resource';
describe('Model: Role', () => {
it('Role model may has many associated users', async () => {
const userHasRole = await create('user_has_role');
await create('user_has_role', { role_id: userHasRole.roleId });
const roleModel = await Role.query().findById(userHasRole.roleId);
const roleUsers = await roleModel.$relatedQuery('users');
expect(roleUsers).to.have.lengthOf(2);
});
it('Role model may has many associated permissions.', async () => {
const roleHasPermissions = await create('role_has_permission');
const roleModel = await Role.query().findById(roleHasPermissions.roleId);
const rolePermissions = await roleModel.$relatedQuery('permissions');
expect(rolePermissions).to.have.lengthOf(1);
});
it('Role model may has many associated resources that has some or all permissions.', async () => {
const roleHasPermissions = await create('role_has_permission');
const roleModel = await Role.query().findById(roleHasPermissions.roleId);
const roleResources = await roleModel.$relatedQuery('resources');
expect(roleResources).to.have.lengthOf(1);
});
});

View File

@@ -1,197 +0,0 @@
import sinon from 'sinon';
import { create, expect } from '~/testInit';
import Setting from '@/models/Setting';
import knex from '../../src/database/knex';
describe('Model: Setting', () => {
afterEach(() => {
Setting.purgeMetadata();
});
describe('Setting.AllMeta()', async () => {
it('Should fetch all metadata from storage in the first call.', async () => {
await create('setting');
const querySpy = sinon.spy(Setting, 'query');
const metadata = await Setting.allMeta();
expect(querySpy.calledOnce).equals(true);
expect(metadata).to.have.lengthOf(1);
querySpy.restore();
});
it('Should get all meta data from stored cache in the second call.', async () => {
await create('setting');
const querySpy = sinon.spy(Setting, 'query');
await Setting.allMeta();
await Setting.allMeta();
expect(querySpy.calledOnce).equals(true);
expect(Setting.metadata).to.have.lengthOf(1);
querySpy.restore();
});
});
describe('Setting.getMeta()', () => {
it('Should fetch metadata of the given key from storage.', async () => {
const setting = await create('setting');
const metadata = await Setting.getMeta(setting.key);
expect(metadata).equals(setting.value);
});
it('Should retrieve the default value if the metadata key was not found.', async () => {
const metadata = await Setting.getMeta('setting', 'default');
expect(metadata).equals('default');
});
it('Should get the same metadata key from cache in the second call.', async () => {
const setting = await create('setting');
await create('setting');
const querySpy = sinon.spy(Setting, 'query');
await Setting.getMeta(setting.key);
expect(querySpy.calledOnce).equals(true);
await Setting.getMeta(setting.key);
expect(querySpy.calledOnce).equals(true);
querySpy.restore();
});
it('Should get the different metadata key from storage.', async () => {
const setting = await create('setting');
const settingAnother = await create('setting');
const querySpy = sinon.spy(Setting, 'query');
await Setting.getMeta(setting.key);
expect(querySpy.calledOnce).equals(true);
await Setting.getMeta(settingAnother.key);
expect(querySpy.calledOnce).equals(true);
querySpy.restore();
});
it('Should hard fetching the metadata from the storage when passing `force` parameter.', async () => {
const setting = await create('setting');
await create('setting');
const querySpy = sinon.spy(Setting, 'query');
await Setting.allMeta();
expect(querySpy.calledOnce).equals(true);
expect(Setting.metadata).to.have.lengthOf(2);
await Setting.getMeta(setting.key, null, true);
expect(querySpy.calledTwice).equals(true);
expect(Setting.metadata).to.have.lengthOf(2);
querySpy.restore();
});
});
describe('Setting.setMeta()', () => {
it('Should mark the given metadata as updated in the stack.', async () => {
const setting = await create('setting');
await Setting.setMeta(setting.key, 'Ahmed');
const foundMeta = Setting.metadata.find((metadata) => (
metadata.key === setting.key && metadata.markAsUpdated === true
&& metadata.value === 'Ahmed'
));
expect(!!foundMeta).equals(true);
});
it('Should mark the set metadata as inserted metadata in the stack.', async () => {
await create('setting');
await Setting.setMeta('key', 'value');
const foundMeta = Setting.metadata.find((metadata) => (
metadata.key === 'key' && metadata.markAsInserted === true
&& metadata.value === 'value'
));
expect(!!foundMeta).equals(true);
});
it('Should fetch the metadata from the storage in case the metadata was exist.', async () => {
const setting = await create('setting');
const querySpy = sinon.spy(Setting, 'query');
await Setting.setMeta(setting.key, 'value');
expect(querySpy.calledOnce).equals(true);
await Setting.setMeta(setting.key, 'updated-value');
expect(querySpy.calledOnce).equals(true);
});
it('Should mark the updated bluk metadata as updated in the stock.', async () => {
});
it('Should mark the inserted bluk metadata as inserted in the stock.', async () => {
});
});
describe('Setting.removeMeta()', () => {
it('Should mark the given metadata as deleted', async () => {
const setting = await create('setting');
await Setting.removeMeta(setting.key);
const foundMeta = Setting.metadata.find((metadata) => (
metadata.key === setting.key && metadata.markAsDeleted === true
));
expect(!!foundMeta).equals(true);
});
it('Should not query the storage when found cached the metadata.', async () => {
const setting = await create('setting');
await Setting.allMeta();
const querySpy = sinon.spy(Setting, 'query');
await Setting.removeMeta(setting.key);
expect(querySpy.calledOnce).equals(false);
querySpy.restore();
});
});
describe('Setting.saveMeta()', () => {
it('Should insert the metadata that set to the stock.', async () => {
await Setting.setMeta('key', 'value');
await Setting.saveMeta();
const storedMetadata = await knex('settings');
expect(storedMetadata).to.have.lengthOf(1);
});
it('Should update the metadata that updated in the stock.', async () => {
const setting = await create('setting');
await Setting.setMeta(setting.key, 'value');
await Setting.saveMeta();
const storedMetadata = await knex('settings');
expect(storedMetadata).to.have.lengthOf(1);
expect(storedMetadata[0].value).equals('value');
});
it('Should delete the metadata that removed from the stock.', async () => {
const setting = await create('setting');
await Setting.removeMeta(setting.key);
await Setting.saveMeta();
const storedMetadata = await knex('settings');
expect(storedMetadata).to.have.lengthOf(0);
});
});
});

View File

@@ -1,46 +1,23 @@
import { create, expect } from '~/testInit';
import User from '@/models/User';
import User from '@/models/TenantUser';
import '@/models/Role';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: User', () => {
describe('relations', () => {
it('User model may has many associated roles.', async () => {
const userHasRole = await create('user_has_role');
await create('user_has_role', { user_id: userHasRole.user_id });
const userHasRole = await tenantFactory.create('user_has_role');
await tenantFactory.create('user_has_role', { user_id: userHasRole.user_id });
const userModel = await User.query().where('id', userHasRole.userId).first();
const userModel = await User.tenant().query().where('id', userHasRole.userId).first();
const userRoles = await userModel.$relatedQuery('roles');
expect(userRoles).to.have.lengthOf(1);
});
});
describe('hasPermissions', () => {
it('Should return true in case user has the given permissions.', async () => {
const resource = await create('resource');
const permission = await create('permission');
const roleHasPerms = await create('role_has_permission', {
resource_id: resource.id,
permission_id: permission.id,
});
const userHasRole = await create('user_has_role', { role_id: roleHasPerms.role_id });
await create('user_has_role', { user_id: userHasRole.user_id });
const userModel = await User.where('id', userHasRole.user_id).fetch();
const hasPermission = await userModel.hasPermissions(resource.name, [permission.name]);
expect(hasPermission).to.equals(true);
});
it('Should return false in case user has no the given permissions.', async () => {
const roleHasPerms = await create('role_has_permission');
const userHasRole = await create('user_has_role', { role_id: roleHasPerms.role_id });
await create('user_has_role', { user_id: userHasRole.user_id });
const userModel = await User.where('id', userHasRole.user_id).fetch();
const hasPermission = await userModel.hasPermissions('resource', ['permission']);
expect(hasPermission).to.equals(false);
});
});
});

View File

@@ -3,37 +3,43 @@ import View from '@/models/View';
import Resource from '@/models/Resource';
import ResourceField from '@/models/ResourceField';
import ViewRole from '@/models/ViewRole';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('Model: View', () => {
it('View model may has many associated resource.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const viewModel = await View.query().findById(view.id);
const viewModel = await View.tenant().query().findById(view.id);
const viewResource = await viewModel.$relatedQuery('resource');
const foundResource = await Resource.query().findById(view.resourceId);
const foundResource = await Resource.tenant().query().findById(view.resourceId);
expect(viewResource.id).equals(foundResource.id);
expect(viewResource.name).equals(foundResource.name);
});
it('View model may has many associated view roles.', async () => {
const view = await create('view');
await create('view_role', { view_id: view.id });
await create('view_role', { view_id: view.id });
const view = await tenantFactory.create('view');
await tenantFactory.create('view_role', { view_id: view.id });
await tenantFactory.create('view_role', { view_id: view.id });
const viewModel = await View.query().findById(view.id);
const viewRoles = await viewModel.$relatedQuery('viewRoles');
const viewModel = await View.tenant().query().findById(view.id);
const viewRoles = await viewModel.$relatedQuery('roles');
expect(viewRoles).to.have.lengthOf(2);
});
it('View model may has many associated view columns', async () => {
const view = await create('view');
await create('view_column', { view_id: view.id });
await create('view_column', { view_id: view.id });
const view = await tenantFactory.create('view');
await tenantFactory.create('view_column', { view_id: view.id });
await tenantFactory.create('view_column', { view_id: view.id });
const viewModel = await View.query().findById(view.id);
const viewModel = await View.tenant().query().findById(view.id);
const viewColumns = await viewModel.$relatedQuery('columns');
expect(viewColumns).to.have.lengthOf(2);

View File

@@ -0,0 +1,31 @@
MYSQL_USER="database_test"
MYSQL_DATABASE="database_test"
MYSQL_CONTAINER_NAME="database_test"
MYSQL_ROOT_PASSWORD="root"
MYSQL_PASSWORD="root"
echo "Start the testing MySql database..."
docker \
run \
--detach \
--env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
--env MYSQL_USER=${MYSQL_USER} \
--env MYSQL_PASSWORD=${MYSQL_PASSWORD} \
--env MYSQL_DATABASE=${MYSQL_DATABASE} \
--name ${MYSQL_CONTAINER_NAME} \
--publish 3306:3306 \
--tmpfs /var/lib/mysql:rw,noexec,nosuid,size=600m \
mysql:5.7;
echo "Sleeping for 10 seconds to allow time for the DB to be provisioned:"
for i in `seq 1 10`;
do
echo "."
sleep 1
done
echo "Database '${MYSQL_DATABASE}' running."
echo " Username: ${MYSQL_USER}"
echo " Password: ${MYSQL_PASSWORD}"

View File

@@ -1,152 +0,0 @@
import { request, expect, create, login } from '~/testInit';
import ManualJournal from '../../src/models/ManualJournal';
import AccountTransaction from '@/models/AccountTransaction';
let loginRes;
describe('routes: `/accountOpeningBalance`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST `/accountOpeningBalance`', () => {
it('Should `accounts` be array type.', async () => {
const res = await request()
.post('/api/accounts_opening_balances')
.send({
accounts: 1000,
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
});
it('Should `accounts.*.id` be integer', async () => {
const res = await request()
.post('/api/accounts_opening_balances')
.send({
accounts: [
{ id: 'id' },
]
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.that.deep.equals({
value: 'id',
msg: 'Invalid value',
param: 'accounts[0].id',
location: 'body',
});
});
it('Should `accounts.*.debit` be numeric.', async () => {
const res = await request()
.post('/api/accounts_opening_balances')
.send({
balance_adjustment_account: 10,
accounts: [{ id: 100, debit: 'id' }],
});
expect(res.status).equals(422);
});
it('Should `accounts.*.id` be exist in the storage.', async () => {
const res = await request()
.post('/api/accounts_opening_balances')
.send({
balance_adjustment_account: 10,
accounts: [
{ id: 100, credit: 100 },
],
});
expect(res.status).equals(422);
expect(res.body.errors).include.something.that.deep.equals({
type: 'NOT_FOUND_ACCOUNT', code: 100, ids: [100],
});
});
it('Should response bad request in case balance adjustment account was not exist.', async () => {
const debitAccount = await create('account');
const creditAccount = await create('account');
const res = await request()
.post('/api/accounts_opening_balances')
.send({
balance_adjustment_account: 10,
accounts: [
{ id: debitAccount.id, credit: 100, debit: 2 },
{ id: creditAccount.id, credit: 0, debit: 100 },
]
});
expect(res.body.errors).include.something.that.deep.equals({
type: 'BALANCE.ADJUSTMENT.ACCOUNT.NOT.EXIST', code: 300,
});
});
it('Should store the manual transaction to the storage.', async () => {
const debitAccount = await create('account');
const creditAccount = await create('account');
const balance = await create('account');
const res = await request()
.post('/api/accounts_opening_balances')
.set('x-access-token', loginRes.body.token)
.send({
balance_adjustment_account: balance.id,
accounts: [
{ id: debitAccount.id, credit: 100, debit: 2 },
{ id: creditAccount.id, credit: 0, debit: 100 },
]
});
const manualJournal = await ManualJournal.query().findById(res.body.id);
expect(manualJournal.amount).equals(100);
expect(manualJournal.transaction_type).equals('OpeningBalance');
});
it('Should store the jouranl entries of account balance transaction.', async () => {
const debitAccount = await create('account');
const creditAccount = await create('account');
const balance = await create('account');
const res = await request()
.post('/api/accounts_opening_balances')
.set('x-access-token', loginRes.body.token)
.send({
balance_adjustment_account: balance.id,
accounts: [
{ id: debitAccount.id, credit: 100, debit: 2 },
{ id: creditAccount.id, credit: 0, debit: 100 },
]
});
const transactions = await AccountTransaction.query()
.where('reference_type', 'OpeningBalance')
.where('reference_id', res.body.id);
expect(transactions.length).equals(2);
});
it('Should adjustment with balance adjustment account with bigger than zero.', async () => {
const debitAccount = await create('account');
const balance = await create('account');
const res = await request()
.post('/api/accounts_opening_balances')
.set('x-access-token', loginRes.body.token)
.send({
balance_adjustment_account: balance.id,
accounts: [
{ id: debitAccount.id, credit: 0, debit: 100 },
]
});
const transactions = await AccountTransaction.query()
.where('reference_type', 'OpeningBalance')
.where('reference_id', res.body.id);
expect(transactions.length).equals(2);
});
});
});

View File

@@ -1,30 +1,26 @@
import {
request,
expect,
create,
login,
} from '~/testInit';
import moment from 'moment';
import ManualJournal from '@/models/ManualJournal';
import AccountTransaction from '@/models/AccountTransaction';
import AccountBalance from '@/models/AccountBalance';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: `/accounting`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('route: `/accounting/make-journal-entries`', async () => {
it('Should sumation of credit or debit does not equal zero.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '123',
@@ -50,10 +46,11 @@ describe('routes: `/accounting`', () => {
});
it('Should all credit entries equal debit.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '123',
@@ -79,12 +76,13 @@ describe('routes: `/accounting`', () => {
});
it('Should journal reference be not exists.', async () => {
const manualJournal = await create('manual_journal');
const account = await create('account');
const manualJournal = await tenantFactory.create('manual_journal');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: manualJournal.journalNumber,
@@ -113,6 +111,7 @@ describe('routes: `/accounting`', () => {
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '123',
@@ -138,12 +137,13 @@ describe('routes: `/accounting`', () => {
});
it('Should discard journal entries that has null credit and debit amount.', async () => {
const account1 = await create('account');
const account2 = await create('account');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '1000',
@@ -169,12 +169,13 @@ describe('routes: `/accounting`', () => {
});
it('Should store manual journal transaction to the storage.', async () => {
const account1 = await create('account');
const account2 = await create('account');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date('2020-2-2').toISOString(),
journal_number: '1000',
@@ -192,7 +193,7 @@ describe('routes: `/accounting`', () => {
],
});
const foundManualJournal = await ManualJournal.query();
const foundManualJournal = await ManualJournal.tenant().query();
expect(foundManualJournal.length).equals(1);
@@ -202,17 +203,19 @@ describe('routes: `/accounting`', () => {
expect(foundManualJournal[0].amount).equals(1000);
expect(moment(foundManualJournal[0].date).format('YYYY-MM-DD')).equals('2020-02-02');
expect(foundManualJournal[0].description).equals('Description here.');
expect(foundManualJournal[0].userId).to.be.a('integer');
expect(foundManualJournal[0].userId).to.be.a('number');
});
it('Should store journal transactions to the storage.', async () => {
const account1 = await create('account');
const account2 = await create('account');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const res = await request()
.post('/api/accounting/make-journal-entries')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
journal_number: '1',
date: new Date('2020-1-1').toISOString(),
reference: '1000',
memo: 'Description here.',
@@ -230,7 +233,7 @@ describe('routes: `/accounting`', () => {
],
});
const foundAccountsTransactions = await AccountTransaction.query();
const foundAccountsTransactions = await AccountTransaction.tenant().query();
expect(foundAccountsTransactions.length).equals(2);
@@ -238,14 +241,14 @@ describe('routes: `/accounting`', () => {
expect(foundAccountsTransactions[0].debit).equals(null);
expect(foundAccountsTransactions[0].accountId).equals(account1.id);
expect(foundAccountsTransactions[0].note).equals('First note');
expect(foundAccountsTransactions[0].transactionType).equals('Journal');
expect(foundAccountsTransactions[0].referenceType).equals('Journal');
expect(foundAccountsTransactions[0].userId).equals(1);
expect(foundAccountsTransactions[1].credit).equals(null);
expect(foundAccountsTransactions[1].debit).equals(1000);
expect(foundAccountsTransactions[1].accountId).equals(account2.id);
expect(foundAccountsTransactions[1].note).equals('Second note');
expect(foundAccountsTransactions[1].transactionType).equals('Journal');
expect(foundAccountsTransactions[1].referenceType).equals('Journal');
expect(foundAccountsTransactions[1].userId).equals(1);
});
});
@@ -255,17 +258,19 @@ describe('routes: `/accounting`', () => {
const res = await request()
.post('/api/manual-journal/1000')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
});
it('Should sumation of credit or debit be equal zero.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '123',
@@ -292,11 +297,12 @@ describe('routes: `/accounting`', () => {
});
it('Should all credit and debit sumation be equal.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: new Date().toISOString(),
journal_number: '123',
@@ -322,8 +328,8 @@ describe('routes: `/accounting`', () => {
});
it('Should response journal number already exists in case another one on the storage.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal2 = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const manualJournal2 = await tenantFactory.create('manual_journal');
const jsonBody = {
date: new Date().toISOString(),
@@ -343,8 +349,9 @@ describe('routes: `/accounting`', () => {
};
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
...jsonBody,
journal_number: manualJournal2.journalNumber,
@@ -356,8 +363,8 @@ describe('routes: `/accounting`', () => {
});
it('Should not response journal number exists in case was unique number.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal2 = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const manualJournal2 = await tenantFactory.create('manual_journal');
const jsonBody = {
date: new Date().toISOString(),
@@ -376,8 +383,9 @@ describe('routes: `/accounting`', () => {
],
};
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
...jsonBody,
journal_number: manualJournal.journalNumber,
@@ -390,8 +398,8 @@ describe('routes: `/accounting`', () => {
})
it('Should response error in case account id not exists in one of the given entries.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal2 = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const manualJournal2 = await tenantFactory.create('manual_journal');
const jsonBody = {
date: new Date().toISOString(),
@@ -410,8 +418,9 @@ describe('routes: `/accounting`', () => {
],
};
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
...jsonBody,
journal_number: manualJournal.journalNumber,
@@ -424,13 +433,14 @@ describe('routes: `/accounting`', () => {
});
it('Should update the given manual journal transaction in the storage.', async () => {
const manualJournal = await create('manual_journal');
const account1 = await create('account');
const account2 = await create('account');
const manualJournal = await tenantFactory.create('manual_journal');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
journal_number: '123',
date: new Date().toISOString(),
@@ -450,7 +460,7 @@ describe('routes: `/accounting`', () => {
],
});
const foundManualJournal = await ManualJournal.query()
const foundManualJournal = await ManualJournal.tenant().query()
.where('id', manualJournal.id);
expect(foundManualJournal.length).equals(1);
@@ -460,21 +470,22 @@ describe('routes: `/accounting`', () => {
});
it('Should update account transactions that associated to the manual journal transaction.', async () => {
const manualJournal = await create('manual_journal');
const account1 = await create('account');
const account2 = await create('account');
const transaction = await create('account_transaction', {
const manualJournal = await tenantFactory.create('manual_journal');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const transaction = await tenantFactory.create('account_transaction', {
reference_type: 'Journal',
reference_id: manualJournal.id,
});
const transaction2 = await create('account_transaction', {
const transaction2 = await tenantFactory.create('account_transaction', {
reference_type: 'Journal',
reference_id: manualJournal.id,
});
const res = await request()
.post(`/api/accounting/manual-journal/${manualJournal.id}`)
.post(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
journal_number: '123',
date: new Date().toISOString(),
@@ -496,7 +507,7 @@ describe('routes: `/accounting`', () => {
],
});
const foundTransactions = await AccountTransaction.query();
const foundTransactions = await AccountTransaction.tenant().query();
expect(foundTransactions.length).equals(2);
expect(foundTransactions[0].credit).equals(0);
@@ -516,6 +527,7 @@ describe('routes: `/accounting`', () => {
const res = await request()
.delete('/api/accounting/manual-journals/1000')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -525,33 +537,36 @@ describe('routes: `/accounting`', () => {
});
it('Should delete manual journal transactions from storage.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const res = await request()
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundManualTransaction = await ManualJournal.query()
const foundManualTransaction = await ManualJournal.tenant().query()
.where('id', manualJournal.id).first();
expect(foundManualTransaction).equals(undefined);
});
it('Should delete associated transactions of journal transaction.', async () => {
const manualJournal = await create('manual_journal');
const transaction1 = await create('account_transaction', {
const manualJournal = await tenantFactory.create('manual_journal');
const transaction1 = await tenantFactory.create('account_transaction', {
reference_type: 'Journal', reference_id: manualJournal.id,
});
const transaction2 = await create('account_transaction', {
const transaction2 = await tenantFactory.create('account_transaction', {
reference_type: 'Journal', reference_id: manualJournal.id,
});
const res = await request()
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundTransactions = await AccountTransaction.query();
const foundTransactions = await AccountTransaction.tenant().query();
expect(foundTransactions.length).equals(0);
});
@@ -565,6 +580,7 @@ describe('routes: `/accounting`', () => {
const res = await request()
.delete('/api/accounting/manual-journals/100')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -582,12 +598,13 @@ describe('routes: `/accounting`', () => {
describe('route: `accounting/manual-journals`', async () => {
it('Should retrieve all manual journals with pagination meta.', async () => {
const manualJournal1 = await create('manual_journal');
const manualJournal2 = await create('manual_journal');
const manualJournal1 = await tenantFactory.create('manual_journal');
const manualJournal2 = await tenantFactory.create('manual_journal');
const res = await request()
.get('/api/accounting/manual-journals')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -599,11 +616,12 @@ describe('routes: `/accounting`', () => {
describe('route: POST `accounting/manual-journals/:id/publish`', () => {
it('Should response not found in case the manual journal id was not exists.', async () => {
const manualJournal = await create('manual_journal');
const manualJournal = await tenantFactory.create('manual_journal');
const res = await request()
.post('/api/accounting/manual-journals/123/publish')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -613,10 +631,12 @@ describe('routes: `/accounting`', () => {
});
it('Should response published ready.', async () => {
const manualJournal = await create('manual_journal', { status: 0 });
const manualJournal = await tenantFactory.create('manual_journal', { status: 1 });
const res = await request()
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(400);
@@ -626,13 +646,13 @@ describe('routes: `/accounting`', () => {
});
it('Should update all accounts transactions to not draft.', async () => {
const manualJournal = await create('manual_journal');
const transaction = await create('account_transaction', {
const manualJournal = await tenantFactory.create('manual_journal', { status: 0 });
const transaction = await tenantFactory.create('account_transaction', {
reference_type: 'Journal',
reference_id: manualJournal.id,
draft: 1,
});
const transaction2 = await create('account_transaction', {
const transaction2 = await tenantFactory.create('account_transaction', {
reference_type: 'Journal',
reference_id: manualJournal.id,
draft: 1,
@@ -640,9 +660,10 @@ describe('routes: `/accounting`', () => {
const res = await request()
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundTransactions = await AccountTransaction.query()
const foundTransactions = await AccountTransaction.tenant().query()
.whereIn('id', [transaction.id, transaction2.id]);
expect(foundTransactions[0].draft).equals(0);

View File

@@ -1,21 +1,24 @@
import { request, expect, create, login } from '~/testInit';
import {
request,
expect,
} from '~/testInit';
import Account from '@/models/Account';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: /accounts/', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST `/accounts`', () => {
it('Should `name` be required.', async () => {
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
});
@@ -24,6 +27,7 @@ describe('routes: /accounts/', () => {
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -34,6 +38,7 @@ describe('routes: /accounts/', () => {
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -41,10 +46,11 @@ describe('routes: /accounts/', () => {
});
it('Should response type not found in case `account_type_id` was not exist.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Account Name',
description: account.description,
@@ -59,10 +65,11 @@ describe('routes: /accounts/', () => {
});
it('Should account code be unique in the storage.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: account.name,
description: account.description,
@@ -77,10 +84,11 @@ describe('routes: /accounts/', () => {
});
it('Should response success with correct data form.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Name',
description: 'description here',
@@ -93,9 +101,11 @@ describe('routes: /accounts/', () => {
});
it('Should store account data in the storage.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request().post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Account Name',
description: 'desc here',
@@ -103,12 +113,10 @@ describe('routes: /accounts/', () => {
parent_account_id: account.id,
});
const accountModel = await Account.query()
const accountModel = await Account.tenant().query()
.where('name', 'Account Name')
.first();
expect(accountModel).a.an('object');
expect(accountModel.description).equals('desc here');
expect(accountModel.accountTypeId).equals(account.accountTypeId);
@@ -118,10 +126,11 @@ describe('routes: /accounts/', () => {
describe('POST `/accounts/:id`', () => {
it('Should `name` be required.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post(`/api/accounts/${account.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -129,10 +138,11 @@ describe('routes: /accounts/', () => {
});
it('Should `account_type_id` be required.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post(`/api/accounts/${account.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -140,10 +150,11 @@ describe('routes: /accounts/', () => {
});
it('Should max length of `code` be limited.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post(`/api/accounts/${account.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -154,17 +165,19 @@ describe('routes: /accounts/', () => {
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
});
it('Should account code be unique in the storage.', async () => {
await create('account', { code: 'ABCD' });
const account = await create('account');
await tenantFactory.create('account', { code: 'ABCD' });
const account = await tenantFactory.create('account');
const res = await request()
.post(`/api/accounts/${account.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'name',
code: 'ABCD',
@@ -178,10 +191,11 @@ describe('routes: /accounts/', () => {
});
it('Should response success with correct data form.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
const res = await request()
.post('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Name',
description: 'description here',
@@ -195,26 +209,15 @@ describe('routes: /accounts/', () => {
});
describe('GET: `/accounts`', () => {
// it('Should retrieve accounts resource not found.', async () => {
// const res = await request()
// .get('/api/accounts')
// .set('x-access-token', loginRes.body.token)
// .send();
// expect(res.status).equals(400);
// expect(res.body.errors).include.something.that.deep.equals({
// type: 'ACCOUNTS_RESOURCE_NOT_FOUND', code: 200,
// });
// });
it('Should retrieve chart of accounts', async () => {
await create('resource', { name: 'accounts' });
const account = await create('account');
await create('account', { parent_account_id: account.id });
await tenantFactory.create('resource', { name: 'accounts' });
const account = await tenantFactory.create('account');
await tenantFactory.create('account', { parent_account_id: account.id });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -222,9 +225,9 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve accounts based on view roles conditionals of the custom view.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const accountTypeField = await create('resource_field', {
const accountTypeField = await tenantFactory.create('resource_field', {
label_name: 'Account type',
key: 'type',
resource_id: resource.id,
@@ -232,28 +235,28 @@ describe('routes: /accounts/', () => {
predefined: true,
});
const accountNameField = await create('resource_field', {
const accountNameField = await tenantFactory.create('resource_field', {
label_name: 'Account Name',
key: 'name',
resource_id: resource.id,
active: true,
predefined: true,
});
const accountsView = await create('view', {
const accountsView = await tenantFactory.create('view', {
name: 'Accounts View',
resource_id: resource.id,
roles_logic_expression: '1 AND 2',
});
const accountType = await create('account_type');
const accountType = await tenantFactory.create('account_type');
await create('view_role', {
await tenantFactory.create('view_role', {
view_id: accountsView.id,
index: 1,
field_id: accountTypeField.id,
value: accountType.name,
comparator: 'equals',
});
await create('view_role', {
await tenantFactory.create('view_role', {
view_id: accountsView.id,
index: 2,
field_id: accountNameField.id,
@@ -261,14 +264,17 @@ describe('routes: /accounts/', () => {
comparator: 'contains',
});
await create('account', { name: 'account-1', account_type_id: accountType.id });
await create('account', { name: 'account-2', account_type_id: accountType.id });
await create('account', { name: 'account-3' });
await tenantFactory.create('account', { name: 'account-1', account_type_id: accountType.id });
await tenantFactory.create('account', { name: 'account-2', account_type_id: accountType.id });
await tenantFactory.create('account', { name: 'account-3' });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.query({ custom_view_id: accountsView.id })
.set('organization-id', tenantWebsite.organizationId)
.query({
custom_view_id: accountsView.id
})
.send();
expect(res.body.accounts.length).equals(2);
@@ -279,23 +285,23 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve accounts based on view roles conditionals with relation join column.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const accountTypeField = await create('resource_field', {
const accountTypeField = await tenantFactory.create('resource_field', {
label_name: 'Account type',
key: 'type',
resource_id: resource.id,
active: true,
predefined: true,
});
const accountsView = await create('view', {
const accountsView = await tenantFactory.create('view', {
name: 'Accounts View',
resource_id: resource.id,
roles_logic_expression: '1',
});
const accountType = await create('account_type');
const accountsViewRole = await create('view_role', {
const accountType = await tenantFactory.create('account_type');
const accountsViewRole = await tenantFactory.create('view_role', {
view_id: accountsView.id,
index: 1,
field_id: accountTypeField.id,
@@ -303,13 +309,14 @@ describe('routes: /accounts/', () => {
comparator: 'equals',
});
await create('account', { account_type_id: accountType.id });
await create('account');
await create('account');
await tenantFactory.create('account', { account_type_id: accountType.id });
await tenantFactory.create('account');
await tenantFactory.create('account');
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
custom_view_id: accountsView.id
})
@@ -320,15 +327,16 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve accounts and child accounts in nested set graph.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const account1 = await create('account');
const account2 = await create('account', { parent_account_id: account1.id });
const account3 = await create('account', { parent_account_id: account2.id });
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account', { parent_account_id: account1.id });
const account3 = await tenantFactory.create('account', { parent_account_id: account2.id });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({ display_type: 'tree' })
.send();
@@ -346,15 +354,16 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve bad request when `filter_roles.*.field_key` not found in accounts resource.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const account1 = await create('account', { name: 'ahmed' });
const account2 = await create('account');
const account3 = await create('account');
const account1 = await tenantFactory.create('account', { name: 'ahmed' });
const account2 = await tenantFactory.create('account');
const account3 = await tenantFactory.create('account');
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
stringified_filter_roles: JSON.stringify([{
condition: 'AND',
@@ -379,27 +388,28 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve filtered accounts according to the given account type filter condition.', async () => {
const resource = await create('resource', { name: 'accounts' });
const keyField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const keyField = await tenantFactory.create('resource_field', {
key: 'type',
resource_id: resource.id,
});
const nameFiled = await create('resource_field', {
const nameFiled = await tenantFactory.create('resource_field', {
key: 'name',
resource_id: resource.id,
});
const accountType = await create('account_type');
const accountType = await tenantFactory.create('account_type');
const account1 = await create('account', {
const account1 = await tenantFactory.create('account', {
name: 'ahmed',
account_type_id: accountType.id
});
const account2 = await create('account');
const account3 = await create('account');
const account2 = await tenantFactory.create('account');
const account3 = await tenantFactory.create('account');
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
stringified_filter_roles: JSON.stringify([{
condition: '&&',
@@ -418,19 +428,20 @@ describe('routes: /accounts/', () => {
});
it('Shoud retrieve filtered accounts according to the given account description filter condition.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const resourceField = await tenantFactory.create('resource_field', {
key: 'description',
resource_id: resource.id,
});
const account1 = await create('account', { name: 'ahmed', description: 'here' });
const account2 = await create('account');
const account3 = await create('account');
const account1 = await tenantFactory.create('account', { name: 'ahmed', description: 'here' });
const account2 = await tenantFactory.create('account');
const account3 = await tenantFactory.create('account');
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
stringified_filter_roles: JSON.stringify([{
condition: 'AND',
@@ -445,24 +456,25 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve filtered accounts based on given filter roles between OR conditions.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const resourceField = await tenantFactory.create('resource_field', {
key: 'description',
resource_id: resource.id,
});
const resourceCodeField = await create('resource_field', {
const resourceCodeField = await tenantFactory.create('resource_field', {
key: 'code',
resource_id: resource.id,
});
const account1 = await create('account', { name: 'ahmed', description: 'target' });
const account2 = await create('account', { description: 'target' });
const account3 = await create('account');
const account1 = await tenantFactory.create('account', { name: 'ahmed', description: 'target' });
const account2 = await tenantFactory.create('account', { description: 'target' });
const account3 = await tenantFactory.create('account');
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
stringified_filter_roles: JSON.stringify([{
condition: '&&',
@@ -484,26 +496,26 @@ describe('routes: /accounts/', () => {
});
it('Should retrieve filtered accounts from custom view and filter roles.', async () => {
const resource = await create('resource', { name: 'accounts' });
const accountTypeField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const accountTypeField = await tenantFactory.create('resource_field', {
key: 'type', resource_id: resource.id,
});
const accountDescriptionField = await create('resource_field', {
const accountDescriptionField = await tenantFactory.create('resource_field', {
key: 'description', resource_id: resource.id,
});
const accountType = await create('account_type', { name: 'type-name' });
const accountType = await tenantFactory.create('account_type', { name: 'type-name' });
const account1 = await create('account', { name: 'ahmed-1' });
const account2 = await create('account', { name: 'ahmed-2', account_type_id: accountType.id, description: 'target' });
const account3 = await create('account', { name: 'ahmed-3' });
const account1 = await tenantFactory.create('account', { name: 'ahmed-1' });
const account2 = await tenantFactory.create('account', { name: 'ahmed-2', account_type_id: accountType.id, description: 'target' });
const account3 = await tenantFactory.create('account', { name: 'ahmed-3' });
const accountsView = await create('view', {
const accountsView = await tenantFactory.create('view', {
name: 'Accounts View',
resource_id: resource.id,
roles_logic_expression: '1',
});
const accountsViewRole = await create('view_role', {
const accountsViewRole = await tenantFactory.create('view_role', {
view_id: accountsView.id,
field_id: accountTypeField.id,
index: 1,
@@ -514,6 +526,7 @@ describe('routes: /accounts/', () => {
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
custom_view_id: accountsView.id,
stringified_filter_roles: JSON.stringify([{
@@ -530,12 +543,13 @@ describe('routes: /accounts/', () => {
});
it('Should validate the given `column_sort_order` column on the accounts resource.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
column_sort_order: 'not_found',
column_sort_by: 'not_found',
sort_order: 'desc',
});
@@ -545,18 +559,19 @@ describe('routes: /accounts/', () => {
});
it('Should sorting the given `column_sort_order` column on asc direction,', async () => {
const resource = await create('resource', { name: 'accounts' });
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const resourceField = await tenantFactory.create('resource_field', {
key: 'name', resource_id: resource.id,
});
const accounts1 = await create('account', { name: 'A' });
const accounts2 = await create('account', { name: 'B' });
const accounts1 = await tenantFactory.create('account', { name: 'A' });
const accounts2 = await tenantFactory.create('account', { name: 'B' });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
column_sort_order: 'name',
column_sort_by: 'name',
sort_order: 'asc',
});
@@ -567,25 +582,25 @@ describe('routes: /accounts/', () => {
});
it('Should sorting the given `column_sort_order` columnw with relation on another table on asc direction.', async () => {
const resource = await create('resource', { name: 'accounts' });
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource', { name: 'accounts' });
const resourceField = await tenantFactory.create('resource_field', {
key: 'type', resource_id: resource.id,
});
const accounts1 = await create('account', { name: 'A' });
const accounts2 = await create('account', { name: 'B' });
const accounts1 = await tenantFactory.create('account', { name: 'A' });
const accounts2 = await tenantFactory.create('account', { name: 'B' });
const res = await request()
.get('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
column_sort_order: 'name',
column_sort_by: 'name',
sort_order: 'asc',
});
expect(res.body.accounts[0].name).equals('A');
expect(res.body.accounts[1].name).equals('B');
});
});
describe('DELETE: `/accounts`', () => {
@@ -593,28 +608,31 @@ describe('routes: /accounts/', () => {
const res = await request()
.delete('/api/accounts/10')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
});
it('Should delete the give account from the storage.', async () => {
const account = await create('account');
const account = await tenantFactory.create('account');
await request()
.delete(`/api/accounts/${account.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundAccounts = await Account.query().where('id', account.id);
const foundAccounts = await Account.tenant().query().where('id', account.id);
expect(foundAccounts).to.have.lengthOf(0);
});
it('Should not delete the given account in case account has associated transactions.', async () => {
const accountTransaction = await create('account_transaction');
const accountTransaction = await tenantFactory.create('account_transaction');
const res = await request()
.delete(`/api/accounts/${accountTransaction.accountId}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(400);
@@ -624,12 +642,12 @@ describe('routes: /accounts/', () => {
});
});
describe('DELETE: `/accounts?ids=`', () => {
it('Should response in case on of accounts ids was not exists.', async () => {
const res = await request()
.delete('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [100, 200],
})
@@ -642,31 +660,33 @@ describe('routes: /accounts/', () => {
});
it('Should response bad request in case one of accounts has transactions.', async () => {
const accountTransaction = await create('account_transaction');
const accountTransaction2 = await create('account_transaction');
const accountTransaction = await tenantFactory.create('account_transaction');
const accountTransaction2 = await tenantFactory.create('account_transaction');
const res = await request()
.delete('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [accountTransaction.accountId, accountTransaction2.accountId],
})
.send();
expect(res.body.errors).include.something.that.deep.equals({
type: 'ACCOUNTS.HAS.TRANSACTIONS',
type: 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS',
code: 300,
ids: [accountTransaction.accountId, accountTransaction2.accountId],
});
});
it('Should delete the given accounts from the storage.', async () => {
const account1 = await create('account');
const account2 = await create('account');
const account1 = await tenantFactory.create('account');
const account2 = await tenantFactory.create('account');
const res = await request()
.delete('/api/accounts')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [account1.id, account2.id],
})
@@ -674,9 +694,66 @@ describe('routes: /accounts/', () => {
expect(res.status).equals(200);
const foundAccounts = await Account.query()
const foundAccounts = await Account.tenant().query()
.whereIn('id', [account1.id, account2.id]);
expect(foundAccounts.length).equals(0);
});
});
describe('POST: `/api/accounts/bulk/activate|inactivate', () => {
it('Should response if there one of accounts ids were not found.', async () => {
const res = await request()
.post('/api/accounts/bulk/activate')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [123123, 321321],
})
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'ACCOUNTS.NOT.FOUND', code: 200,
});
});
it('Should activate all the given accounts.', async () => {
const accountA = await tenantFactory.create('account', { active: 1 });
const accountB = await tenantFactory.create('account', { active: 1 });
const res = await request()
.post('/api/accounts/bulk/inactivate')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [accountA.id, accountB.id],
})
.send();
const updatedAccounts = await Account.tenant().query().whereIn('id', [accountA.id, accountB.id]);
expect(updatedAccounts[0].active).equals(0);
expect(updatedAccounts[1].active).equals(0);
});
it('Should inactivate all the given accounts.', async () => {
const accountA = await tenantFactory.create('account', { active: 0 });
const accountB = await tenantFactory.create('account', { active: 0 });
const res = await request()
.post('/api/accounts/bulk/activate')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [accountA.id, accountB.id],
})
.send();
const updatedAccounts = await Account.tenant().query().whereIn('id', [accountA.id, accountB.id]);
expect(updatedAccounts[0].active).equals(1);
expect(updatedAccounts[1].active).equals(1);
});
});
});

View File

@@ -1,6 +1,16 @@
import { request, expect, create } from '~/testInit';
import { request, expect, createUser } from '~/testInit';
import { hashPassword } from '@/utils';
import knex from '@/database/knex';
import {
tenantWebsite,
tenantFactory,
systemFactory,
loginRes
} from '~/dbInit';
import TenantUser from '@/models/TenantUser';
import PasswordReset from '@/system/models/PasswordReset';
import SystemUser from '@/system/models/SystemUser';
describe('routes: /auth/', () => {
describe('POST `/api/auth/login`', () => {
@@ -59,33 +69,35 @@ describe('routes: /auth/', () => {
});
it('Should not authenticate in case user was not active.', async () => {
const user = await create('user', { active: false });
const res = await request().post('/api/auth/login').send({
crediential: user.email,
password: 'incorrect_password',
const user = await createUser(tenantWebsite, {
active: false,
email: 'admin@admin.com',
});
const res = await request().post('/api/auth/login').send({
crediential: 'admin@admin.com',
password: 'admin',
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'INCORRECT_PASSWORD', code: 110,
type: 'USER_INACTIVE', code: 110,
});
});
it('Should authenticate with correct email and password and active user.', async () => {
const user = await create('user', {
password: hashPassword('admin'),
const user = await createUser(tenantWebsite, {
email: 'admin@admin.com',
});
const res = await request().post('/api/auth/login').send({
crediential: user.email,
password: 'admin',
});
expect(res.status).equals(200);
});
it('Should autheticate success with correct phone number and password.', async () => {
const password = await hashPassword('admin');
const user = await create('user', {
const user = await createUser(tenantWebsite, {
phone_number: '0920000000',
password,
});
@@ -98,15 +110,20 @@ describe('routes: /auth/', () => {
});
it('Should last login date be saved after success login.', async () => {
const user = await create('user', {
password: hashPassword('admin'),
const user = await createUser(tenantWebsite, {
email: 'admin@admin.com',
});
const res = await request().post('/api/auth/login').send({
crediential: user.email,
password: 'admin',
});
const foundUserAfterUpdate = await TenantUser.tenant().query()
.where('email', user.email)
.where('first_name', user.first_name)
.first();
expect(res.status).equals(200);
expect(foundUserAfterUpdate.lastLoginAt).to.not.be.null;
});
});
@@ -132,17 +149,18 @@ describe('routes: /auth/', () => {
email: 'admin@admin.com',
});
expect(res.status).equals(422);
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'EMAIL_NOT_FOUND', code: 100,
type: 'EMAIL.NOT.REGISTERED', code: 200,
});
});
it('Should delete all already tokens that associate to the given email.', async () => {
const user = await create('user');
const user = await createUser(tenantWebsite);
const token = '123123';
await knex('password_resets').insert({ email: user.email, token });
await request().post('/api/auth/send_reset_password').send({
email: user.email,
});
@@ -153,7 +171,7 @@ describe('routes: /auth/', () => {
});
it('Should store new token associate with the given email.', async () => {
const user = await create('user');
const user = await createUser(tenantWebsite);
await request().post('/api/auth/send_reset_password').send({
email: user.email,
});
@@ -164,7 +182,7 @@ describe('routes: /auth/', () => {
});
it('Should response success if the email was exist.', async () => {
const user = await create('user');
const user = await createUser(tenantWebsite);
const res = await request().post('/api/auth/send_reset_password').send({
email: user.email,
});
@@ -183,63 +201,88 @@ describe('routes: /auth/', () => {
});
it('Should `password` be required.', async () => {
const passwordReset = await create('password_reset');
const res = await request().post(`/api/reset/${passwordReset.token}`).send();
const user = await createUser(tenantWebsite);
const passwordReset = await systemFactory.create('password_reset', {
email: user.email,
});
const res = await request()
.post(`/api/auth/reset/${passwordReset.token}`)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('VALIDATION_ERROR');
expect(res.body.code).equals('validation_error');
const paramsErrors = res.body.errors.map((error) => error.param);
expect(paramsErrors).to.include('password');
});
it('Should password and confirm_password be equal.', async () => {
const passwordReset = await create('password_reset');
const res = await request().post(`/api/reset/${passwordReset.token}`).send({
password: '123123',
const user = await createUser(tenantWebsite);
const passwordReset = await systemFactory.create('password_reset', {
email: user.email,
});
const res = await request()
.post(`/api/auth/reset/${passwordReset.token}`)
.send({
password: '123123',
});
expect(res.status).equals(422);
expect(res.body.code).equals('VALIDATION_ERROR');
expect(res.body.code).equals('validation_error');
const paramsErrors = res.body.errors.map((error) => error.param);
expect(paramsErrors).to.include('password');
});
it('Should response success with correct data form.', async () => {
const passwordReset = await create('password_reset');
const res = await request().post(`/api/reset/${passwordReset.token}`).send({
password: '123123',
confirm_password: '123123',
const user = await createUser(tenantWebsite);
const passwordReset = await systemFactory.create('password_reset', {
email: user.email,
});
const res = await request()
.post(`/api/auth/reset/${passwordReset.token}`)
.send({
password: '123123',
confirm_password: '123123',
});
expect(res.status).equals(200);
});
it('Should token be deleted after success response.', async () => {
const passwordReset = await create('password_reset');
await request().post(`/api/reset/${passwordReset.token}`).send({
password: '123123',
confirm_password: '123123',
const user = await createUser(tenantWebsite);
const passwordReset = await systemFactory.create('password_reset', {
email: user.email,
});
await request()
.post(`/api/auth/reset/${passwordReset.token}`)
.send({
password: '123123',
confirm_password: '123123',
});
const foundTokens = await PasswordReset.query().where('email', passwordReset.email);
const foundTokens = await knex('password_resets').where('email', passwordReset.email);
expect(foundTokens).to.have.lengthOf(0);
});
it('Should password be updated after success response.', async () => {
const user = await create('user');
const passwordReset = await create('password_reset', { user_id: user.id });
const user = await createUser(tenantWebsite);
const passwordReset = await systemFactory.create('password_reset', {
email: user.email,
});
await request().post(`/api/reset/${passwordReset.token}`).send({
const res = await request().post(`/api/auth/reset/${passwordReset.token}`).send({
password: '123123',
confirm_password: '123123',
});
const systemUserPasswordUpdated = await SystemUser.query()
.where('id', user.id).first();
const foundUser = await knex('users').where('id', user.id);
expect(foundUser.id).equals(user.id);
expect(foundUser.password).not.equals(user.password);
expect(systemUserPasswordUpdated.id).equals(user.id);
expect(systemUserPasswordUpdated.password).not.equals(user.password);
});
});
});

View File

@@ -1,10 +0,0 @@
describe('Authorization', () => {
it('Should response unauthorized in case use has no role has permissions to the given resource.', () => {
});
it('Should response authorized in case user has role has all permissions.', () => {
});
});

View File

@@ -1,262 +0,0 @@
import {
request,
expect,
create,
login,
} from '~/testInit';
import Budget from '@/models/Budget';
import BudgetEntry from '@/models/BudgetEntry';
let loginRes;
describe('routes: `/budget`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/budget', () => {
it('Should `name` be required.', async () => {
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token).send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.that.deep.equal({
msg: 'Invalid value', param: 'name', location: 'body',
});
});
it('Should `period` be required.', async () => {
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token).send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.that.deep.equal({
msg: 'Invalid value', param: 'period', location: 'body',
});
});
it('Should `fiscal_year` be required.', async () => {
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.errors).include.something.that.deep.equal({
msg: 'Invalid value', param: 'fiscal_year', location: 'body',
});
});
it('Should `entries` alteast one item', () => {
});
it('Should account id be exist in the storage.', async () => {
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token)
.send({
name: 'Budget Name',
fiscal_year: '2020',
period: 'year',
accounts_type: 'profit_loss',
accounts: [
{
account_id: 100,
entries: [
{
amount: 1000,
order: 1,
},
],
},
],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'ACCOUNT.NOT.FOUND', code: 200, accounts: [100],
});
});
it('Should response success with budget id after post valid data.', async () => {
const account = await create('account');
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token)
.send({
name: 'Budget Name',
fiscal_year: '2020',
period: 'year',
accounts_type: 'profit_loss',
accounts: [
{
account_id: account.id,
entries: [
{
amount: 1000,
order: 1,
},
],
},
],
});
expect(res.status).equals(200);
});
it('Should save budget to the storage.', async () => {
const account = await create('account');
const res = await request()
.post('/api/budget')
.set('x-access-token', loginRes.body.token)
.send({
name: 'Budget Name',
fiscal_year: '2020',
period: 'year',
accounts_type: 'profit_loss',
accounts: [
{
account_id: account.id,
entries: [
{
amount: 1000,
order: 1,
}
],
},
],
});
// const storedBudget = await Budget.query().findById(res.body.id);
// expect(storedBudget.name).equals('Budget Name');
const storedBudgetEntries = await BudgetEntry.query()
.where('budget_id', storedBudget.id)
.where('account_id', account.id);
expect(storedBudgetEntries.length).equals(1);
});
it('Should save budget entries to the storage.', () => {
});
it('Should response success with correct data format.', () => {
});
});
describe('GET: `/budget/:id`', () => {
it('Should response not found in case budget id was not found.', async () => {
const budget = await create('budget');
const res = await request()
.get('/api/budget/1000')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(404);
});
it('Should retrieve columns of budget year date range with year period.', async () => {
const budget = await create('budget', { period: 'year' });
const res = await request()
.get(`/api/budget/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(1);
});
it('Should retrieve columns of budget year range with month period.', async () => {
const budget = await create('budget', {
period: 'month',
});
const res = await request()
.get(`/api/budget/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(12);
});
it('Should retrieve columns of budget year range with quarter period.', async () => {
const budget = await create('budget', {
period: 'quarter',
});
const res = await request()
.get(`/api/budget/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(4);
});
it('Should retrieve columns of budget year range with half year period.', async () => {
const budget = await create('budget', {
period: 'half-year',
});
const res = await request()
.get(`/api/budget/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(2);
});
it('Should retrieve budget accounts with associated entries.', async () => {
const budget = await create('budget', { period: 'year' });
const budgetEntry = await create('budget_entry', {
budget_id: budget.id,
});
const res = await request()
.get(`/api/budget/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body);
});
});
describe('DELETE: `/budget/:id`', () => {
it('Should response not found in case budget id was not found.', () => {
});
it('Should delete budget from the storage', () => {
});
it('Should delete budget entries from the storage.', () => {
});
it('Should response success in case budget was exists before the delete.', () => {
});
});
describe('GET: `/budget`', () => {
it('Should retrieve all budgets with pagination metadata.', async () => {
const res = await request()
.get('/api/budget')
.set('x-access-token', loginRes.body.token)
.send();
console.log(res.body);
expect(res.status).equals(200);
})
})
});

View File

@@ -1,67 +0,0 @@
import {
request,
expect,
create,
login,
} from '~/testInit';
let loginRes;
describe('routes: `/budget_reports`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('GET: `/budget_verses_actual/:reportId`', () => {
it('Should retrieve columns of budget year range with quarter period.', async () => {
const budget = await create('budget', { period: 'quarter' });
const budgetEntry = await create('budget_entry', { budget_id: budget.id });
const res = await request()
.get(`/api/budget_reports/budget_verses_actual/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(4);
});
it('Should retrieve columns of budget year range with month period.', async () => {
const budget = await create('budget', { period: 'month' });
const budgetEntry = await create('budget_entry', { budget_id: budget.id });
const res = await request()
.get(`/api/budget_reports/budget_verses_actual/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(12);
});
it('Should retrieve columns of budget year range with year period.', async () => {
const budget = await create('budget', { period: 'year' });
const budgetEntry = await create('budget_entry', { budget_id: budget.id });
const res = await request()
.get(`/api/budget_reports/budget_verses_actual/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(1);
});
it('Should retrieve columns of budget year range with half-year period.', async () => {
const budget = await create('budget', { period: 'half-year' });
const budgetEntry = await create('budget_entry', { budget_id: budget.id });
const res = await request()
.get(`/api/budget_reports/budget_verses_actual/${budget.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.columns.length).equals(2);
});
});
});

View File

@@ -1,36 +1,31 @@
import {
request,
create,
expect,
login,
} from '~/testInit';
import Currency from '@/models/Currency';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('route: /currencies/', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/api/currencies`', () => {
it('Should response unauthorized in case user was not logged in.', async () => {
const res = await request()
.post('/api/currencies')
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `currency_name` be required.', async () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -44,6 +39,7 @@ describe('route: /currencies/', () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -54,11 +50,12 @@ describe('route: /currencies/', () => {
});
it('Should response currency code is duplicated.', async () => {
create('currency', { currency_code: 'USD' });
tenantFactory.create('currency', { currency_code: 'USD' });
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
@@ -74,12 +71,13 @@ describe('route: /currencies/', () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
});
const foundCurrency = await Currency.query().where('currency_code', 'USD');
const foundCurrency = await Currency.tenant().query().where('currency_code', 'USD');
expect(foundCurrency.length).equals(1);
expect(foundCurrency[0].currencyCode).equals('USD');
@@ -90,6 +88,7 @@ describe('route: /currencies/', () => {
const res = await request()
.post('/api/currencies')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
currency_code: 'USD',
currency_name: 'Dollar',
@@ -100,27 +99,28 @@ describe('route: /currencies/', () => {
});
describe('DELETE: `/api/currencies/:currency_code`', () => {
it('Should delete the given currency code from the storage.', async () => {
const currency = await create('currency');
const currency = await tenantFactory.create('currency');
const res = await request()
.delete(`/api/currencies/${currency.currencyCode}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
const foundCurrency = await Currency.query().where('currency_code', 'USD');
const foundCurrency = await Currency.tenant().query().where('currency_code', 'USD');
expect(foundCurrency.length).equals(0);
});
});
describe('POST: `/api/currencies/:id`', () => {
it('Should `currency_name` be required.', async () => {
const currency = await create('currency');
const currency = await tenantFactory.create('currency');
const res = await request()
.post(`/api/currencies/${currency.code}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -131,10 +131,11 @@ describe('route: /currencies/', () => {
});
it('Should `currency_code` be required.', async () => {
const currency = await create('currency');
const currency = await tenantFactory.create('currency');
const res = await request()
.post(`/api/currencies/${currency.code}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -145,12 +146,13 @@ describe('route: /currencies/', () => {
});
it('Should response currency code is duplicated.', async () => {
const currency1 = await create('currency');
const currency2 = await create('currency');
const currency1 = await tenantFactory.create('currency');
const currency2 = await tenantFactory.create('currency');
const res = await request()
.post(`/api/currencies/${currency2.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
currency_code: currency1.currencyCode,
currency_name: 'Dollar',
@@ -163,18 +165,19 @@ describe('route: /currencies/', () => {
});
it('Should update currency details of the given currency on the storage.', async () => {
const currency1 = await create('currency');
const currency2 = await create('currency');
const currency1 = await tenantFactory.create('currency');
const currency2 = await tenantFactory.create('currency');
const res = await request()
.post(`/api/currencies/${currency2.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
currency_code: 'ABC',
currency_name: 'Name',
});
const foundCurrency = await Currency.query().where('currency_code', 'ABC');
const foundCurrency = await Currency.tenant().query().where('currency_code', 'ABC');
expect(foundCurrency.length).equals(1);
expect(foundCurrency[0].currencyCode).equals('ABC');

View File

@@ -1,21 +1,17 @@
import moment from 'moment';
import {
request,
create,
expect,
login,
} from '~/testInit';
import ExchangeRate from '../../src/models/ExchangeRate';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe.only('route: /exchange_rates/', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('route: /exchange_rates/', () => {
describe('POST: `/api/exchange_rates`', () => {
it('Should response unauthorized in case the user was not logged in.', async () => {
const res = await request()
@@ -23,13 +19,14 @@ describe.only('route: /exchange_rates/', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `currency_code` be required.', async () => {
const res = await request()
.post('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -43,6 +40,7 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.post('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -56,6 +54,7 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.post('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -66,7 +65,7 @@ describe.only('route: /exchange_rates/', () => {
});
it('Should response date and currency code is already exists.', async () => {
await create('exchange_rate', {
await tenantFactory.create('exchange_rate', {
date: '2020-02-02',
currency_code: 'USD',
exchange_rate: 4.4,
@@ -74,6 +73,7 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.post('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: '2020-02-02',
currency_code: 'USD',
@@ -90,6 +90,7 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.post('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: '2020-02-02',
currency_code: 'USD',
@@ -97,7 +98,7 @@ describe.only('route: /exchange_rates/', () => {
});
expect(res.status).equals(200);
const foundExchangeRate = await ExchangeRate.query()
const foundExchangeRate = await ExchangeRate.tenant().query()
.where('currency_code', 'USD');
expect(foundExchangeRate.length).equals(1);
@@ -111,13 +112,14 @@ describe.only('route: /exchange_rates/', () => {
describe('GET: `/api/exchange_rates', () => {
it('Should retrieve all exchange rates with pagination meta.', async () => {
await create('exchange_rate');
await create('exchange_rate');
await create('exchange_rate');
await tenantFactory.create('exchange_rate');
await tenantFactory.create('exchange_rate');
await tenantFactory.create('exchange_rate');
const res = await request()
.get('/api/exchange_rates')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -130,6 +132,7 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.post('/api/exchange_rates/100')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
date: '2020-02-02',
currency_code: 'USD',
@@ -143,16 +146,17 @@ describe.only('route: /exchange_rates/', () => {
});
it('Should update exchange rate of the given id on the storage.', async () => {
const exRate = await create('exchange_rate');
const exRate = await tenantFactory.create('exchange_rate');
const res = await request()
.post(`/api/exchange_rates/${exRate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
exchange_rate: 4.4,
});
expect(res.status).equals(200);
const foundExchangeRate = await ExchangeRate.query()
const foundExchangeRate = await ExchangeRate.tenant().query()
.where('id', exRate.id);
expect(foundExchangeRate.length).equals(1);
@@ -165,7 +169,9 @@ describe.only('route: /exchange_rates/', () => {
const res = await request()
.delete('/api/exchange_rates/100')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'EXCHANGE.RATE.NOT.FOUND', code: 200,
@@ -173,14 +179,52 @@ describe.only('route: /exchange_rates/', () => {
});
it('Should delete the given exchange rate id from the storage.', async () => {
const exRate = await create('exchange_rate');
const exRate = await tenantFactory.create('exchange_rate');
const res = await request()
.delete(`/api/exchange_rates/${exRate.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundRates = await ExchangeRate.query();
const foundRates = await ExchangeRate.tenant().query();
expect(foundRates.length).equals(0);
});
});
describe('DELETE: `/api/exchange_rates/bulk`', () => {
it('Should response the given exchange rates ids where not found.', async () => {
const res = await request()
.delete('/api/exchange_rates/bulk')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [12332, 32432],
})
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'EXCHANGE.RATES.IS.NOT.FOUND', code: 200, ids: [12332, 32432],
})
});
it('Should delete the given excahnge rates ids.', async () => {
const exRate = await tenantFactory.create('exchange_rate');
const exRate2 = await tenantFactory.create('exchange_rate');
const res = await request()
.delete('/api/exchange_rates/bulk')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [exRate.id, exRate2.id],
})
.send();
const foundExchangeRate = await ExchangeRate.tenant().query()
.whereIn('id', [exRate.id, exRate2.id]);
expect(foundExchangeRate.length).equals(0);
})
});
});

View File

@@ -1,491 +0,0 @@
import {
request,
expect,
create,
login,
} from '~/testInit';
import AccountTransaction from '@/models/AccountTransaction';
import Expense from '@/models/Expense';
import ResourceFieldMetadata from '@/models/ResourceFieldMetadata';
let loginRes;
let expenseType;
let cashType;
let expenseAccount;
let cashAccount;
describe('routes: /expenses/', () => {
beforeEach(async () => {
loginRes = await login();
expenseType = await create('account_type', { normal: 'debit' });
cashType = await create('account_type', { normal: 'debit' });
expenseAccount = await create('account', { account_type_id: expenseType.id });
cashAccount = await create('account', { account_type_id: cashType.id });
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/expenses`', () => {
it('Should response unauthorized in case user was not authorized.', async () => {
const res = await request().post('/api/expenses').send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should `payment_account_id` be required.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.errors).include.something.that.deep.equals({
msg: 'Invalid value',
param: 'payment_account_id',
location: 'body',
});
});
it('Should `expense_account_id` be required.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.errors).include.something.that.deep.equals({
msg: 'Invalid value',
param: 'expense_account_id',
location: 'body',
});
});
it('Should `amount` be required.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.errors).include.something.that.deep.equals({
msg: 'Invalid value',
param: 'amount',
location: 'body',
});
});
it('Should `exchange_rate` be required in case `currency_code` not equal default one.', () => {
});
it('Should response bad request in case expense account was not found.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: 100,
payment_account_id: 100,
amount: 100,
});
expect(res.body.errors).include.something.that.deep.equals({
type: 'EXPENSE.ACCOUNT.NOT.FOUND', code: 200,
});
});
it('Should response bad request in case payment account was not found.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: 100,
payment_account_id: 100,
amount: 100,
});
expect(res.body.errors).include.something.that.deep.equals({
type: 'PAYMENT.ACCOUNT.NOT.FOUND', code: 100,
});
});
it('Should response success with valid required data.', async () => {
const res = await request().post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: expenseAccount.id,
payment_account_id: cashAccount.id,
amount: 100,
});
expect(res.status).equals(200);
});
it('Should record journal entries of expense transaction.', async () => {
const res = await request()
.post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: expenseAccount.id,
payment_account_id: cashAccount.id,
amount: 100,
});
const expensesEntries = await AccountTransaction.query()
.where('reference_type', 'Expense')
.where('reference_id', res.body.id);
expect(expensesEntries.length).equals(2);
});
it('Should save expense transaction to the storage.', async () => {
const res = await request()
.post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: expenseAccount.id,
payment_account_id: cashAccount.id,
amount: 100,
});
const expenseTransaction = await Expense.query().where('id', res.body.id);
expect(expenseTransaction.amount).equals(100);
});
it('Should response bad request in case custom field slug was not exists in the storage.', async () => {
const res = await request()
.post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: expenseAccount.id,
payment_account_id: cashAccount.id,
amount: 100,
custom_options: [
{
key: 'random_key',
value: 'Value here',
},
],
});
expect(res.status).equals(400);
});
it('Should save expense custom fields to the storage.', async () => {
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', {
resource_id: resource.id,
slug: 'custom_field_1',
});
const res = await request()
.post('/api/expenses')
.set('x-access-token', loginRes.body.token)
.send({
expense_account_id: expenseAccount.id,
payment_account_id: cashAccount.id,
amount: 100,
custom_fields: [
{
key: 'custom_field_1',
value: 'Value here',
},
],
});
const storedResourceItemMetadata = await ResourceFieldMetadata.query()
.where('resource_id', resource.id)
.where('resource_item_id', res.body.id);
expect(storedResourceItemMetadata.metadata.length).equals(1);
expect(storedResourceItemMetadata.metadata[0].resourceId).equals(resource.id);
expect(storedResourceItemMetadata.metadata[0].resourceItemId).equals(res.body.id);
expect(storedResourceItemMetadata.metadata[0].key).equals('custom_field_1');
expect(storedResourceItemMetadata.metadata[0].value).equals('Value here');
});
});
describe('POST: `/expenses/:id`', () => {
it('Should response unauthorized in case user was not authorized.', () => {
});
it('Should response not found in case expense was not exist.', () => {
});
it('Should update the expense transaction.', () => {
});
});
describe('DELETE: `/expenses/:id`', () => {
it('Should response not found in case expense not found.', async () => {
const res = await request()
.delete('/api/expenses/1000')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.body.errors).include.something.that.deep.equals({
type: 'EXPENSE.TRANSACTION.NOT.FOUND', code: 100,
});
});
it('Should response success in case expense transaction was exist.', async () => {
const expense = await create('expense');
const res = await request()
.delete(`/api/expenses/${expense.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(200);
});
it('Should delete the expense transaction from the storage.', async () => {
const expense = await create('expense');
await request()
.delete(`/api/expenses/${expense.id}`)
.set('x-access-token', loginRes.body.token)
.send();
const storedExpense = await Expense.query().findById(expense.id);
expect(storedExpense).equals(undefined);
});
it('Should delete the journal entries that associated to expense transaction from the storage.', async () => {
const expense = await create('expense');
await request()
.delete(`/api/expense/${expense.id}`)
.set('x-access-token', loginRes.body.token)
.send();
const expenseEntries = await AccountTransaction.query()
.where('reference_type', 'Expense')
.where('reference_id', expense.id);
expect(expenseEntries.length).equals(0);
});
it('Should reverse accounts balance that associated to expense transaction.', () => {
});
it('Should delete the custom fields that associated to resource and resource item.', () => {
});
});
describe('POST: `/expenses/bulk`', () => {
it('Should response unauthorized in case user was not authorized.', async () => {
const res = await request().post('/api/expenses/bluk').send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should response bad request in case expenses was not array.', async () => {
const res = await request()
.post('/api/expenses/bulk')
.set('x-access-token', loginRes.body.token)
.send({
expenses: 'Not array :(',
});
expect(res.body.errors).include.something.that.deep.equals({
value: 'Not array :(',
msg: 'Invalid value',
param: 'expenses',
location: 'body',
});
});
it('Should response bad request in case one expense account was not found.', async () => {
const res = await request()
.post('/api/expenses/bulk')
.set('x-access-token', loginRes.body.token)
.send({
expenses: [
{
payment_account_id: 100,
expense_account_id: 100,
amount: 1000,
},
],
});
expect(res.body.reasons).include.something.that.deep.equals({
type: 'EXPENSE.ACCOUNTS.NOT.FOUND', code: 200, accounts: [100],
});
});
it('Should response bad request in case one of payment account was not found.', async () => {
const res = await request()
.post('/api/expenses/bulk')
.set('x-access-token', loginRes.body.token)
.send({
expenses: [
{
payment_account_id: 100,
expense_account_id: 100,
amount: 1000,
},
],
});
expect(res.body.reasons).include.something.that.deep.equals({
type: 'PAYMENY.ACCOUNTS.NOT.FOUND', code: 100, accounts: [100],
});
});
it('Should store expenses transactions to the storage.', async () => {
const res = await request()
.post('/api/expenses/bulk')
.set('x-access-token', loginRes.body.token)
.send({
expenses: [
{
payment_account_id: cashAccount.id,
expense_account_id: expenseAccount.id,
amount: 1000,
},
{
payment_account_id: cashAccount.id,
expense_account_id: expenseAccount.id,
amount: 1000,
},
],
});
const expenseTransactions = await Expense.query();
expect(expenseTransactions.length).equals(2);
});
it('Should store journal entries of expenses transactions to the storage.', async () => {
const res = await request()
.post('/api/expenses/bulk')
.set('x-access-token', loginRes.body.token)
.send({
expenses: [
{
payment_account_id: cashAccount.id,
expense_account_id: expenseAccount.id,
amount: 1000,
},
{
payment_account_id: cashAccount.id,
expense_account_id: expenseAccount.id,
amount: 1000,
},
],
});
const expenseJournalEntries = await AccountTransaction.query();
expect(expenseJournalEntries.length).equals(4);
});
});
describe('POST: `/expenses/:id/publish`', () => {
it('Should response not found in case the expense id was not exist.', async () => {
const expense = await create('expense', { published: false });
const res = await request()
.post('/api/expenses/100/publish')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'EXPENSE.NOT.FOUND', code: 100,
});
});
it('Should response bad request in case expense is already published.', async () => {
const expense = await create('expense', { published: true });
const res = await request()
.post(`/api/expenses/${expense.id}/publish`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'EXPENSE.ALREADY.PUBLISHED', code: 200,
});
});
it('Should publish the expense transaction.', async () => {
const expense = await create('expense', { published: false });
const res = await request()
.post(`/api/expenses/${expense.id}/publish`)
.set('x-access-token', loginRes.body.token)
.send();
const storedExpense = await Expense.query().findById(expense.id);
expect(storedExpense.published).equals(1);
});
it('Should publish the journal entries that associated to the given expense transaction.', async () => {
const expense = await create('expense', { published: false });
const transaction = await create('account_transaction', {
reference_id: expense.id,
reference_type: 'Expense',
});
const res = await request()
.post(`/api/expenses/${expense.id}/publish`)
.set('x-access-token', loginRes.body.token)
.send();
const entries = await AccountTransaction.query()
.where('reference_id', expense.id)
.where('reference_type', 'Expense');
entries.forEach((entry) => {
expect(entry.draft).equals(0);
});
});
it('Should response success in case expense was exist and not published.', async () => {
const expense = await create('expense', { published: false });
const res = await request()
.post(`/api/expenses/${expense.id}/publish`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(200);
});
});
describe('GET: `/expenses/:id`', () => {
it('Should response view not found in case the custom view id was not exist.', async () => {
const expense = await create('expense');
const res = await request()
.get(`/api/expenses/${expense.id}123`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'EXPENSE.TRANSACTION.NOT.FOUND', code: 100,
});
});
it('Should retrieve custom fields metadata.', async () => {
const expense = await create('expense');
const resource = await create('resource', { name: 'Expense' });
const resourceField = await create('resource_field', {
resource_id: resource.id,
slug: 'custom_field_1',
});
const resourceFieldMetadata = await create('resource_custom_field_metadata', {
resource_id: resource.id,
resource_item_id: expense.id,
key: 'custom_field_1',
});
const res = await request()
.get(`/api/expenses/${expense.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(200);
expect(res.body.custom_fields.length).equals(1);
expect(res.body.custom_fields[0].key).equals('custom_field_1');
expect(res.body.custom_fields[0].value).equals(resourceFieldMetadata.value);
});
});
});

View File

@@ -1,338 +0,0 @@
import {
create,
expect,
request,
login,
} from '~/testInit';
import knex from '@/database/knex';
import ResourceField from '@/models/ResourceField';
import e from 'express';
import Fields from '../../src/http/controllers/Fields';
let loginRes;
describe('route: `/fields`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/fields/:resource_id`', () => {
it('Should response unauthorized in case the user was not authorized.', async () => {
const res = await request()
.post('/api/fields/resource/items')
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
});
it('Should response bad request in case resource name was not exist.', async () => {
const res = await request()
.post('/api/fields/resource/not_found_resource')
.set('x-access-token', loginRes.body.token)
.send({
label: 'Extra Field',
data_type: 'text',
});
expect(res.status).equals(404);
expect(res.body.errors).include.something.deep.equals({
type: 'RESOURCE_NOT_FOUND', code: 100,
});
});
it('Should `label` be required.', async () => {
const resource = await create('resource');
const res = await request()
.post(`/api/fields/resource/${resource.resource_name}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'label', location: 'body',
});
});
it('Should `data_type` be required.', async () => {
const resource = await create('resource');
const res = await request()
.post(`/api/fields/resource/${resource.resource_id}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'data_type', location: 'body',
});
});
it('Should `data_type` be one in the list.', async () => {
const resource = await create('resource');
const res = await request()
.post(`/api/fields/resource/${resource.resource_id}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'invalid_type',
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'data_type', location: 'body', value: 'invalid_type',
});
});
it('Should `value` be boolean valid value in case `data_type` was `boolean`.', () => {
});
it('Should `value` be URL valid value in case `data_type` was `url`.', () => {
});
it('Should `value` be integer valid value in case `data_type` was `number`.', () => {
});
it('Should `value` be decimal valid value in case `data_type` was `decimal`.', () => {
});
it('Should `value` be email valid value in case `data_type` was `email`.', () => {
});
it('Should `value` be boolean valid value in case `data_type` was `checkbox`.', () => {
});
it('Should response not found in case resource name was not exist.', async () => {
const res = await request()
.post('/api/fields/resource/resource_not_found')
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
});
expect(res.status).equals(404);
expect(res.body.errors).include.something.that.deep.equals({
type: 'RESOURCE_NOT_FOUND', code: 100,
});
});
it('Should response success with valid data.', async () => {
const resource = await create('resource');
const res = await request()
.post(`/api/fields/resource/${resource.name}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
});
expect(res.status).equals(200);
});
it('Should store the given field details to the storage.', async () => {
const resource = await create('resource');
const res = await request()
.post(`/api/fields/resource/${resource.name}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
options: ['option 1', 'option 2'],
});
const foundField = await ResourceField.query().findById(res.body.id);
expect(foundField.labelName).equals('Field label');
expect(foundField.dataType).equals('text');
expect(foundField.default).equals('default value');
expect(foundField.helpText).equals('help text');
expect(foundField.options.length).equals(2);
});
});
describe('POST: `/fields/:field_id`', () => {
it('Should response unauthorized in case the user was not authorized.', async () => {
const field = await create('resource_field');
const res = await request()
.post(`/api/fields/${field.id}`)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
});
it('Should `label` be required.', async () => {
const field = await create('resource_field');
const res = await request()
.post(`/api/fields/${field.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'label', location: 'body',
})
});
it('Should `data_type` be required.', async () => {
const field = await create('resource_field');
const res = await request()
.post(`/api/fields/${field.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'data_type', location: 'body',
});
});
it('Should `data_type` be one in the list.', async () => {
const field = await create('resource_field');
const res = await request().post(`/api/fields/${field.id}`).send({
label: 'Field label',
data_type: 'invalid_type',
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
value: 'invalid_type',
msg: 'Invalid value',
param: 'data_type',
location: 'body',
});
});
it('Should response not found in case resource field id was not exist.', async () => {
const res = await request()
.post('/api/fields/100')
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
});
expect(res.status).equals(404);
expect(res.body.errors).include.something.that.deep.equals({
type: 'FIELD_NOT_FOUND', code: 100,
});
});
it('Should update details of the given resource field.', async () => {
const field = await create('resource_field');
const res = await request()
.post(`/api/fields/${field.id}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
});
const updateField = await ResourceField.query().findById(res.body.id);
expect(updateField.labelName).equals('Field label');
expect(updateField.dataType).equals('text');
expect(updateField.default).equals('default value');
expect(updateField.helpText).equals('help text');
});
it('Should save the new options of the field with exist ones in the storage.', async () => {
const field = await create('resource_field', {
options: JSON.stringify([{ key: 1, value: 'Option 1' }]),
});
const res = await request()
.post(`/api/fields/${field.id}`)
.set('x-access-token', loginRes.body.token)
.send({
label: 'Field label',
data_type: 'text',
default: 'default value',
help_text: 'help text',
options: [
{ key: 1, value: 'Value Key 1' },
{ key: 2, value: 'Value Key 2' },
],
});
const updateField = await ResourceField.query().findById(res.body.id);
expect(updateField.options.length).equals(2);
expect(updateField.options[0].key).equals(1);
expect(updateField.options[1].key).equals(2);
expect(updateField.options[0].value).equals('Value Key 1');
expect(updateField.options[1].value).equals('Value Key 2');
});
});
describe('POST: `/fields/status/:field_id`', () => {
it('Should response not found in case field id was not exist.', async () => {
const res = await request().post('/api/fields/status/100').send();
expect(res.status).equals(404);
});
it('Should change status activation of the given field.', async () => {
const field = await create('resource_field');
const res = await request()
.post(`/api/fields/status/${field.id}`)
.set('x-access-token', loginRes.body.token)
.send({
active: false,
});
const storedField = await knex('resource_fields').where('id', field.id).first();
expect(storedField.active).equals(0);
});
});
describe('DELETE: `/fields/:field_id`', () => {
it('Should response not found in case field id was not exist.', async () => {
const res = await request().delete('/api/fields/100').send();
expect(res.status).equals(404);
});
it('Should not delete predefined field.', async () => {
const field = await create('resource_field', { predefined: true });
const res = await request().delete(`/api/fields/${field.id}`).send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'PREDEFINED_FIELD', code: 100,
});
});
it('Should delete the given field from the storage.', async () => {
const field = await create('resource_field');
const res = await request().delete(`/api/fields/${field.id}`).send();
expect(res.status).equals(200);
});
});
});

View File

@@ -1,57 +1,68 @@
import moment from 'moment';
import {
expect,
request,
expect,
login,
create,
createTenantFactory,
createTenant,
dropTenant,
} from '~/testInit';
let tenantWebsite;
let tenantFactory;
let loginRes;
let creditAccount;
let debitAccount;
describe('routes: `/financial_statements`', () => {
beforeEach(async () => {
loginRes = await login();
tenantWebsite = await createTenant();
tenantFactory = createTenantFactory(tenantWebsite.tenantDb);
loginRes = await login(tenantWebsite);
// Balance sheet types.
const creditAccType = await create('account_type', { normal: 'credit', balance_sheet: true });
const debitAccType = await create('account_type', { normal: 'debit', balance_sheet: true });
const creditAccType = await tenantFactory.create('account_type', { normal: 'credit', balance_sheet: true });
const debitAccType = await tenantFactory.create('account_type', { normal: 'debit', balance_sheet: true });
// Income statement types.
const incomeType = await create('account_type', { normal: 'credit', income_sheet: true });
const expenseType = await create('account_type', { normal: 'debit', income_sheet: true });
const incomeType = await tenantFactory.create('account_type', { normal: 'credit', income_sheet: true });
const expenseType = await tenantFactory.create('account_type', { normal: 'debit', income_sheet: true });
// Assets & liabilites accounts.
creditAccount = await create('account', { account_type_id: creditAccType.id });
debitAccount = await create('account', { account_type_id: debitAccType.id });
creditAccount = await tenantFactory.create('account', { account_type_id: creditAccType.id });
debitAccount = await tenantFactory.create('account', { account_type_id: debitAccType.id });
// Income && expenses accounts.
const incomeAccount = await create('account', { account_type_id: incomeType.id });
const expenseAccount = await create('account', { account_type_id: expenseType.id });
const income2Account = await create('account', { account_type_id: incomeType.id });
const incomeAccount = await tenantFactory.create('account', { account_type_id: incomeType.id });
const expenseAccount = await tenantFactory.create('account', { account_type_id: expenseType.id });
const income2Account = await tenantFactory.create('account', { account_type_id: incomeType.id });
const accountTransactionMixied = { date: '2020-1-10' };
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
credit: 1000, debit: 0, account_id: creditAccount.id, referenceType: 'Expense', ...accountTransactionMixied,
});
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
credit: 1000, debit: 0, account_id: creditAccount.id, ...accountTransactionMixied,
});
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
debit: 2000, credit: 0, account_id: debitAccount.id, ...accountTransactionMixied,
});
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
debit: 2000, credit: 0, account_id: debitAccount.id, ...accountTransactionMixied,
});
await create('account_transaction', { credit: 2000, account_id: incomeAccount.id, ...accountTransactionMixied });
await create('account_transaction', { debit: 6000, account_id: expenseAccount.id, ...accountTransactionMixied });
await tenantFactory.create('account_transaction', { credit: 2000, account_id: incomeAccount.id, ...accountTransactionMixied });
await tenantFactory.create('account_transaction', { debit: 6000, account_id: expenseAccount.id, ...accountTransactionMixied });
});
afterEach(() => {
afterEach(async () => {
await dropTenant(tenantWebsite);
loginRes = null;
tenantFactory = null;
});
describe('routes: `/financial_statements/journal`', () => {
it('Should response unauthorized in case the user was not authorized.', async () => {
const res = await request()
@@ -65,6 +76,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -83,6 +95,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2018-01-01',
to_date: '2019-01-01',
@@ -96,6 +109,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
account_ids: [creditAccount.id],
})
@@ -108,6 +122,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
transaction_types: ['Expense'],
});
@@ -119,6 +134,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_range: 2000,
to_range: 2000,
@@ -140,6 +156,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/journal')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
number_format: {
divide_1000: true,
@@ -167,6 +184,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.query.from_date).equals(moment().startOf('year').format('YYYY-MM-DD'));
@@ -182,6 +200,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.accounts).is.an('array');
@@ -201,6 +220,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const targetAccount = res.body.accounts.find((a) => a.id === creditAccount.id);
@@ -218,6 +238,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-20',
to_date: '2020-03-30',
@@ -240,6 +261,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
none_zero: true,
})
@@ -262,6 +284,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-20',
to_date: '2020-03-30',
@@ -277,6 +300,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-20',
to_date: '2020-03-30',
@@ -293,6 +317,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2020-03-30',
@@ -311,6 +336,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2020-03-30',
@@ -326,13 +352,14 @@ describe('routes: `/financial_statements`', () => {
});
it('Should amount transactions rounded with no decimals when `number_format.no_cents` is `true`.', async () => {
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
debit: 0.25, credit: 0, account_id: debitAccount.id, date: '2020-1-10',
});
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2020-03-30',
@@ -351,6 +378,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/general_ledger')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2020-03-30',
@@ -376,6 +404,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'year',
from_date: '2020-01-01',
@@ -397,6 +426,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'year',
})
@@ -410,6 +440,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_type: 'total',
from_date: '2012-01-01',
@@ -431,6 +462,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'year',
from_date: '2012-01-01',
@@ -484,6 +516,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'day',
from_date: '2020-01-08',
@@ -504,6 +537,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'month',
from_date: '2019-07-01',
@@ -534,6 +568,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'quarter',
from_date: '2020-01-01',
@@ -551,12 +586,13 @@ describe('routes: `/financial_statements`', () => {
});
it('Should retrieve the balance sheet amounts without cents.', async () => {
await create('account_transaction', {
await tenantFactory.create('account_transaction', {
debit: 0.25, credit: 0, account_id: debitAccount.id, date: '2020-1-10',
});
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'quarter',
from_date: '2020-01-01',
@@ -580,6 +616,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'quarter',
from_date: '2020',
@@ -603,6 +640,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
display_columns_by: 'quarter',
from_date: '2002',
@@ -632,6 +670,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/trial_balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const foundCreditAccount = res.body.items.find((item) => {
@@ -646,6 +685,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/trial_balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
// There is no transactions between these dates.
from_date: '2002-01-01',
@@ -661,6 +701,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/trial_balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
// There is no transactions between these dates.
from_date: '2020-01-05',
@@ -680,6 +721,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/trial_balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
// There is no transactions between these dates.
from_date: '2020-01-05',
@@ -702,6 +744,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/trial_balance_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
// There is no transactions between these dates.
from_date: '2020-01-05',
@@ -732,6 +775,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2020-12-12',
@@ -755,6 +799,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: moment().startOf('year').format('YYYY-MM-DD'),
to_date: moment().endOf('year').format('YYYY-MM-DD'),
@@ -773,6 +818,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
to_date: moment('2020-01-01').endOf('month').format('YYYY-MM-DD'),
@@ -801,6 +847,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
to_date: moment('2020-01-01').endOf('month').format('YYYY-MM-DD'),
@@ -818,6 +865,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
to_date: toDate,
@@ -838,6 +886,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2021-01-01',
@@ -854,6 +903,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2021-01-01',
@@ -870,6 +920,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2019-12-01',
to_date: '2020-12-01',
@@ -887,6 +938,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2019-12-01',
to_date: '2020-12-01',
@@ -904,6 +956,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2019-12-01',
to_date: '2020-12-01',
@@ -920,6 +973,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2019-12-01',
to_date: '2020-12-01',
@@ -942,6 +996,7 @@ describe('routes: `/financial_statements`', () => {
const res = await request()
.get('/api/financial_statements/profit_loss_sheet')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
from_date: '2020-01-01',
to_date: '2021-01-01',

View File

@@ -1,21 +1,16 @@
import {
request,
create,
expect,
login,
} from '~/testInit';
import knex from '@/database/knex';
import Item from '@/models/Item';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: `/items`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/items`', () => {
it('Should not create a new item if the user was not authorized.', async () => {
const res = await request()
@@ -23,21 +18,14 @@ describe('routes: `/items`', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should user have create permission to create a new item.', async () => {
const loginRes = await login();
const res = await request().post('/api/items')
.set('x-access-token', loginRes.body.token).send();
expect(res.status).equals(401);
expect(res.body.message).equals('Unauthorized');
});
it('Should `name` be required.', async () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -51,6 +39,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -64,6 +53,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
type: 'not-defined',
});
@@ -80,6 +70,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
cost_price: 'not_numeric',
});
@@ -98,6 +89,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
sell_price: 'not_numeric',
});
@@ -116,6 +108,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
cost_account_id: 'not_numeric',
});
@@ -134,6 +127,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
sell_account_id: 'not_numeric',
});
@@ -160,6 +154,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'inventory',
@@ -180,6 +175,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -200,6 +196,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -219,6 +216,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -238,6 +236,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -255,13 +254,14 @@ describe('routes: `/items`', () => {
});
it('Should response success with correct data format.', async () => {
const account = await create('account');
const anotherAccount = await create('account');
const itemCategory = await create('item_category');
const account = await tenantFactory.create('account');
const anotherAccount = await tenantFactory.create('account');
const itemCategory = await tenantFactory.create('item_category');
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -274,6 +274,42 @@ describe('routes: `/items`', () => {
expect(res.status).equals(200);
});
it('Should store the given item details to the storage.', async () => {
const account = await tenantFactory.create('account');
const anotherAccount = await tenantFactory.create('account');
const itemCategory = await tenantFactory.create('item_category');
const res = await request()
.post('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
sku: 'SKU CODE',
sell_price: 10.2,
cost_price: 20.2,
sell_account_id: account.id,
cost_account_id: anotherAccount.id,
category_id: itemCategory.id,
note: 'note about item'
});
const storedItem = await Item.tenant().query().where('id', res.body.id).first();
expect(storedItem.name).equals('Item Name');
expect(storedItem.type).equals('service');
expect(storedItem.sellPrice).equals(10.2);
expect(storedItem.costPrice).equals(20.2);
expect(storedItem.sellAccountId).equals(account.id);
expect(storedItem.costAccountId).equals(anotherAccount.id);
expect(storedItem.categoryId).equals(itemCategory.id);
expect(storedItem.sku).equals('SKU CODE');
expect(storedItem.note).equals('note about item');
expect(storedItem.userId).is.not.null;
});
});
describe('POST: `items/:id`', () => {
@@ -281,6 +317,7 @@ describe('routes: `/items`', () => {
const res = await request()
.post('/api/items/100')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'product',
@@ -298,10 +335,11 @@ describe('routes: `/items`', () => {
});
it('Should `name` be required.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -312,10 +350,11 @@ describe('routes: `/items`', () => {
});
it('Should `type` be required.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -326,10 +365,11 @@ describe('routes: `/items`', () => {
});
it('Should `sell_price` be numeric.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
sell_price: 'not_numeric',
});
@@ -345,10 +385,11 @@ describe('routes: `/items`', () => {
});
it('Should `cost_price` be numeric.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
cost_price: 'not_numeric',
});
@@ -364,10 +405,11 @@ describe('routes: `/items`', () => {
});
it('Should `sell_account_id` be integer.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
sell_account_id: 'not_numeric',
});
@@ -383,10 +425,11 @@ describe('routes: `/items`', () => {
});
it('Should `cost_account_id` be integer.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
cost_account_id: 'not_numeric',
});
@@ -401,11 +444,12 @@ describe('routes: `/items`', () => {
});
});
it('Should response bad request in case cost account was not exist.', async () => {
const item = await create('item');
it ('Should response bad request in case cost account was not exist.', async () => {
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'service',
@@ -422,17 +466,18 @@ describe('routes: `/items`', () => {
});
it('Should response bad request in case sell account was not exist.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Item Name',
type: 'product',
sell_price: 10.2,
cost_price: 20.2,
sell_account_id: 10,
cost_account_id: 20,
sell_account_id: 1000000,
cost_account_id: 1000000,
});
expect(res.status).equals(400);
@@ -442,14 +487,15 @@ describe('routes: `/items`', () => {
});
it('Should update details of the given item.', async () => {
const account = await create('account');
const anotherAccount = await create('account');
const itemCategory = await create('item_category');
const account = await tenantFactory.create('account');
const anotherAccount = await tenantFactory.create('account');
const itemCategory = await tenantFactory.create('item_category');
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.post(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'New Item Name',
type: 'service',
@@ -460,7 +506,7 @@ describe('routes: `/items`', () => {
category_id: itemCategory.id,
});
const updatedItem = await Item.query().findById(item.id);
const updatedItem = await Item.tenant().query().findById(item.id);
expect(updatedItem.name).equals('New Item Name');
expect(updatedItem.type).equals('service');
@@ -477,29 +523,32 @@ describe('routes: `/items`', () => {
const res = await request()
.delete('/api/items/10')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
});
it('Should response success in case was exist.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
const res = await request()
.delete(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
});
it('Should delete the given item from the storage.', async () => {
const item = await create('item');
const item = await tenantFactory.create('item');
await request()
.delete(`/api/items/${item.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const storedItems = await Item.query().where('id', item.id);
const storedItems = await Item.tenant().query().where('id', item.id);
expect(storedItems).to.have.lengthOf(0);
});
});
@@ -511,31 +560,17 @@ describe('routes: `/items`', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should response items resource not found.', async () => {
await create('item');
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equal({
type: 'ITEMS_RESOURCE_NOT_FOUND',
code: 200,
});
expect(res.body.message).equals('Unauthorized');
});
it('Should retrieve items list with associated accounts.', async () => {
await create('resource', { name: 'items' });
await create('item');
await tenantFactory.create('resource', { name: 'items' });
await tenantFactory.create('item');
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -551,12 +586,13 @@ describe('routes: `/items`', () => {
});
it('Should retrieve ordered items based on the given `column_sort_order` and `sort_order` query.', async () => {
await create('item', { name: 'ahmed' });
await create('item', { name: 'mohamed' });
await tenantFactory.create('item', { name: 'ahmed' });
await tenantFactory.create('item', { name: 'mohamed' });
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
column_sort_order: 'name',
sort_order: 'desc',
@@ -569,11 +605,12 @@ describe('routes: `/items`', () => {
});
it('Should retrieve pagination meta of items list.', async () => {
await create('resource', { name: 'items' });
await tenantFactory.create('resource', { name: 'items' });
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.items.results).to.be.a('array');
@@ -584,26 +621,27 @@ describe('routes: `/items`', () => {
});
it('Should retrieve filtered items based on custom view conditions.', async () => {
const item1 = await create('item', { type: 'service' });
const item2 = await create('item', { type: 'service' });
const item3 = await create('item', { type: 'inventory' });
const item4 = await create('item', { type: 'inventory' });
const item1 = await tenantFactory.create('item', { type: 'service' });
const item2 = await tenantFactory.create('item', { type: 'service' });
const item3 = await tenantFactory.create('item', { type: 'inventory' });
const item4 = await tenantFactory.create('item', { type: 'inventory' });
const view = await create('view', {
const view = await tenantFactory.create('view', {
name: 'Items Inventory',
resource_id: 2,
roles_logic_expression: '1',
});
const viewCondition = await create('view_role', {
const viewCondition = await tenantFactory.create('view_role', {
view_id: view.id,
index: 1,
field_id: 11,
field_id: 12,
value: 'inventory',
comparator: 'equals',
});
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
custom_view_id: view.id,
})
@@ -618,14 +656,15 @@ describe('routes: `/items`', () => {
});
it('Should retrieve filtered items based on filtering conditions.', async () => {
const item1 = await create('item', { type: 'service' });
const item2 = await create('item', { type: 'service', name: 'target' });
const item3 = await create('item', { type: 'inventory' });
const item4 = await create('item', { type: 'inventory' });
const item1 = await tenantFactory.create('item', { type: 'service' });
const item2 = await tenantFactory.create('item', { type: 'service', name: 'target' });
const item3 = await tenantFactory.create('item', { type: 'inventory' });
const item4 = await tenantFactory.create('item', { type: 'inventory' });
const res = await request()
.get('/api/items')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
stringified_filter_roles: JSON.stringify([
{

View File

@@ -1,33 +1,28 @@
import {
request,
expect,
create,
login,
} from '~/testInit';
import knex from '@/database/knex';
let loginRes;
import ItemCategory from '@/models/ItemCategory';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
describe('routes: /item_categories/', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST `/items_categories``', async () => {
it('Should not create a item category if the user was not authorized.', async () => {
const res = await request().post('/api/item_categories').send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `name` be required.', async () => {
const res = await request()
.post('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -38,6 +33,7 @@ describe('routes: /item_categories/', () => {
const res = await request()
.post('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Clothes',
parent_category_id: 10,
@@ -53,6 +49,7 @@ describe('routes: /item_categories/', () => {
const res = await request()
.post('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Clothes',
description: 'Here is description',
@@ -66,10 +63,11 @@ describe('routes: /item_categories/', () => {
});
it('Should item category data be saved to the storage.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.post('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Clothes',
description: 'Here is description',
@@ -78,8 +76,9 @@ describe('routes: /item_categories/', () => {
expect(res.status).equals(200);
const storedCategory = await knex('items_categories')
.where('id', res.body.category.id).first();
const storedCategory = await ItemCategory.tenant().query()
.where('id', res.body.category.id)
.first();
expect(storedCategory.name).equals('Clothes');
expect(storedCategory.description).equals('Here is description');
@@ -90,32 +89,33 @@ describe('routes: /item_categories/', () => {
describe('POST `/items_category/{id}`', () => {
it('Should not update a item category if the user was not authorized.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.post(`/api/item_categories/${category.id}`)
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `name` be required.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.post(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.send({
name: '',
});
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
});
it('Should `parent_category_id` be exist in the storage.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.post(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Name',
parent_category_id: 10,
@@ -128,12 +128,13 @@ describe('routes: /item_categories/', () => {
});
it('Should response success with correct data format.', async () => {
const category = await create('item_category');
const anotherCategory = await create('item_category');
const category = await tenantFactory.create('item_category');
const anotherCategory = await tenantFactory.create('item_category');
const res = await request()
.post(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Name',
parent_category_id: anotherCategory.id,
@@ -144,20 +145,22 @@ describe('routes: /item_categories/', () => {
});
it('Should item category data be update in the storage.', async () => {
const category = await create('item_category');
const anotherCategory = await create('item_category');
const category = await tenantFactory.create('item_category');
const anotherCategory = await tenantFactory.create('item_category');
const res = await request()
.post(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'Name',
parent_category_id: anotherCategory.id,
description: 'updated description',
});
const storedCategory = await knex('items_categories')
.where('id', res.body.id).first();
const storedCategory = await ItemCategory.tenant().query()
.where('id', res.body.id)
.first();
expect(storedCategory.name).equals('Name');
expect(storedCategory.description).equals('updated description');
@@ -167,43 +170,48 @@ describe('routes: /item_categories/', () => {
describe('DELETE: `/items_categories`', async () => {
it('Should not delete the give item category if the user was not authorized.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.delete(`/api/item_categories/${category.id}`)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should not delete if the item category was not found.', async () => {
const res = await request()
.delete('/api/item_categories/10')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
});
it('Should response success after delete the given item category.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.delete(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
});
it('Should delete the give item category from the storage.', async () => {
const category = await create('item_category');
const category = await tenantFactory.create('item_category');
const res = await request()
.delete(`/api/item_categories/${category.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const categories = await knex('items_categories').where('id', category.id);
const categories = await ItemCategory.tenant().query()
.where('id', category.id);
expect(categories).to.have.lengthOf(0);
});
@@ -212,12 +220,13 @@ describe('routes: /item_categories/', () => {
describe('GET: `/item_categories`', () => {
it('Should retrieve list of item categories.', async () => {
const category1 = await create('item_category');
const category2 = await create('item_category', { parent_category_id: category1.id });
const category1 = await tenantFactory.create('item_category');
const category2 = await tenantFactory.create('item_category', { parent_category_id: category1.id });
const res = await request()
.get('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.categories).to.be.a('array');
@@ -233,14 +242,15 @@ describe('routes: /item_categories/', () => {
it('Should retrieve of related items.', async () => {
const category1 = await create('item_category');
const category2 = await create('item_category', { parent_category_id: category1.id });
const category1 = await tenantFactory.create('item_category');
const category2 = await tenantFactory.create('item_category', { parent_category_id: category1.id });
await create('item', { category_id: category1.id });
await tenantFactory.create('item', { category_id: category1.id });
const res = await request()
.get('/api/item_categories')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.categories[0].count).to.be.a('number');
@@ -261,4 +271,41 @@ describe('routes: /item_categories/', () => {
});
});
describe('DELETE: `/items_cateogires`', () => {
it('Should response bad request in case one of item categories id not exists in the storage.', async () => {
const res = await request()
.delete('/api/item_categories/bulk')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [1020, 2020],
})
.send();
expect(res.status).equals(400);
expect(res.body.errors).include.something.deep.equals({
type: 'ITEM.CATEGORIES.IDS.NOT.FOUND', code: 200
});
});
it('Should delete the given item categories.', async () => {
const itemCategory = await tenantFactory.create('item_category');
const itemCategory2 = await tenantFactory.create('item_category');
const res = await request()
.delete('/api/item_categories/bulk')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
ids: [itemCategory.id, itemCategory2.id],
})
.send();
const deleteItemCategories = await ItemCategory.tenant().query()
.whereIn('id', [itemCategory.id, itemCategory2.id]);
expect(deleteItemCategories.length).equals(0);
});
});
});

View File

@@ -1,10 +0,0 @@
import { request, expect } from '~/testInit';
describe('routes: /oauth2/', () => {
describe('POST `/api/oauth/token`', () => {
it('Should `crediential` be required.', async () => {
const res = await request().post('/api/oauth2/token').send({});
expect(res.status).equals(200);
});
});
});

View File

@@ -1,23 +1,16 @@
import knex from '@/database/knex';
import {
request,
expect,
create,
make,
login,
} from '~/testInit';
import Option from '@/models/Option';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: `/options`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('POST: `/options/`', () => {
it('Should response unauthorized if the user was not logged in.', async () => {
const res = await request()
@@ -25,13 +18,14 @@ describe('routes: `/options`', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should response the options key and group is not defined.', async () => {
const res = await request()
.post('/api/options')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
options: [
{
@@ -56,6 +50,7 @@ describe('routes: `/options`', () => {
const res = await request()
.post('/api/options')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
options: [{
key: 'name',
@@ -65,7 +60,7 @@ describe('routes: `/options`', () => {
});
expect(res.status).equals(200);
const storedOptions = await Option.query()
const storedOptions = await Option.tenant().query()
.where('group', 'organization')
.where('key', 'name');
@@ -83,16 +78,17 @@ describe('routes: `/options`', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should retrieve options the associated to the given group.', async () => {
await create('option', { group: 'organization', key: 'name' });
await create('option', { group: 'organization', key: 'base_currency' });
await tenantFactory.create('option', { group: 'organization', key: 'name' });
await tenantFactory.create('option', { group: 'organization', key: 'base_currency' });
const res = await request()
.get('/api/options')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
group: 'organization',
})
@@ -104,12 +100,13 @@ describe('routes: `/options`', () => {
});
it('Should retrieve options that associated to the given key.', async () => {
await create('option', { group: 'organization', key: 'base_currency' });
await create('option', { group: 'organization', key: 'name' });
await tenantFactory.create('option', { group: 'organization', key: 'base_currency' });
await tenantFactory.create('option', { group: 'organization', key: 'name' });
const res = await request()
.get('/api/options')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({
key: 'name',
})

View File

@@ -1,276 +0,0 @@
import { request, expect, create } from '~/testInit';
import knex from '@/database/knex';
describe('routes: `/roles/`', () => {
describe('POST: `/roles/`', () => {
it('Should `name` be required.', async () => {
const res = await request().post('/api/roles').send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundNameParam = res.body.errors.find((err) => err.param === 'name');
expect(!!foundNameParam).equals(true);
});
it('Should `permissions` be array.', async () => {
const res = await request().post('/api/roles').send({
permissions: 'not_array',
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPermissionsPerm = res.body.errors.find((err) => err.param === 'permissions');
expect(!!foundPermissionsPerm).equals(true);
});
it('Should `permissions.resource_slug` be slug.', async () => {
const res = await request().post('/api/roles').send({
permissions: [{ slug: 'not slug' }],
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPerm = res.body.errors.find((err) => err.param === 'permissions[0].resource_slug');
expect(!!foundPerm).equals(true);
});
it('Should `permissions.permissions be array.`', async () => {
const res = await request().post('/api/roles').send({
permissions: [{ permissions: 'not_array' }],
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPerm = res.body.errors.find((err) => err.param === 'permissions[0].permissions');
expect(!!foundPerm).equals(true);
});
it('Should response bad request in case the resource slug was invalid.', async () => {
const res = await request().post('/api/roles').send({
name: 'name',
permissions: [{ resource_slug: 'invalid', permissions: ['item'] }],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'RESOURCE_SLUG_NOT_FOUND',
code: 100,
resources: ['invalid'],
});
});
it('Should response bad request in case the permission type was invalid.', async () => {
const res = await request().post('/api/roles').send({
name: 'name',
permissions: [{ resource_slug: 'items', permissions: ['item'] }],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'PERMISSIONS_SLUG_NOT_FOUND',
code: 200,
permissions: [{ resource_slug: 'items', permissions: ['item'] }],
});
});
it('Should save the submit resources in the storage in case was not exist.', async () => {
await request().post('/api/roles').send({
name: 'Role Name',
permissions: [{ resource_slug: 'items', permissions: ['create'] }],
});
const storedResources = await knex('resources');
expect(storedResources).to.have.lengthOf(1);
});
it('Should save the submit permissions in the storage in case was not exist.', async () => {
await request().post('/api/roles').send({
name: 'Role Name',
permissions: [{ resource_slug: 'items', permissions: ['create'] }],
});
const storedPermissions = await knex('permissions');
expect(storedPermissions).to.have.lengthOf(1);
});
it('Should save the submit role in the storage with associated resource and permissions.', async () => {
await request().post('/api/roles').send({
name: 'Role Name',
description: 'Role description',
permissions: [{ resource_slug: 'items', permissions: ['create', 'view'] }],
});
const storedRoles = await knex('roles');
const storedResource = await knex('resources').where('name', 'items').first();
const storedPermissions = await knex('permissions');
const roleHasPermissions = await knex('role_has_permissions')
.where('role_id', storedRoles[0].id);
expect(storedRoles).to.have.lengthOf(1);
expect(storedRoles[0].name).equals('Role Name');
expect(storedRoles[0].description).equals('Role description');
expect(roleHasPermissions).to.have.lengthOf(2);
expect(roleHasPermissions[0].role_id).equals(storedRoles[0].id);
expect(roleHasPermissions[0].permission_id).equals(storedPermissions[0].id);
expect(roleHasPermissions[0].resource_id).equals(storedResource.id);
});
it('Should response success with correct data format.', async () => {
const res = await request().post('/api/roles').send();
expect(res.status).equals(422);
});
it('Should save the given role details in the storage.', async () => {
const res = await request().post('/api/roles').send();
expect(res.status).equals(422);
});
});
describe('POST: `/roles/:id`', () => {
it('Should response not found in case role was not exist.', async () => {
const res = await request().post('/api/roles/10').send({
name: 'Role Name',
description: 'Description',
permissions: [
{ resource_slug: 'items', permissions: ['create'] },
],
});
expect(res.status).equals(404);
});
it('Should `name` be required.', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send();
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundNameParam = res.body.errors.find((err) => err.param === 'name');
expect(!!foundNameParam).equals(true);
});
it('Should `permissions` be array.', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send({
permissions: 'not_array',
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPermissionsPerm = res.body.errors.find((err) => err.param === 'permissions');
expect(!!foundPermissionsPerm).equals(true);
});
it('Should `permissions.resource_slug` be slug.', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send({
permissions: [{ slug: 'not slug' }],
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPerm = res.body.errors.find((err) => err.param === 'permissions[0].resource_slug');
expect(!!foundPerm).equals(true);
});
it('Should `permissions.permissions be array.`', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send({
permissions: [{ permissions: 'not_array' }],
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
const foundPerm = res.body.errors.find((err) => err.param === 'permissions[0].permissions');
expect(!!foundPerm).equals(true);
});
it('Should response bad request in case the resource slug was invalid.', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send({
name: 'name',
permissions: [{ resource_slug: 'invalid', permissions: ['item'] }],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'RESOURCE_SLUG_NOT_FOUND',
code: 100,
resources: ['invalid'],
});
});
it('Should response bad request in case the permission type was invalid.', async () => {
const role = await create('role');
const res = await request().post(`/api/roles/${role.id}`).send({
name: 'name',
permissions: [{ resource_slug: 'items', permissions: ['item'] }],
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'PERMISSIONS_SLUG_NOT_FOUND',
code: 200,
permissions: [{ resource_slug: 'items', permissions: ['item'] }],
});
});
it('Should save the submit resources in the storage in case was not exist.', async () => {
const role = await create('role');
await request().post(`/api/roles/${role.id}`).send({
name: 'Role Name',
permissions: [{ resource_slug: 'items', permissions: ['create'] }],
});
const storedResources = await knex('resources');
expect(storedResources).to.have.lengthOf(1);
});
it('Should save the submit permissions in the storage in case was not exist.', async () => {
const role = await create('role');
await request().post(`/api/roles/${role.id}`).send({
name: 'Role Name',
permissions: [{ resource_slug: 'items', permissions: ['create'] }],
});
const storedPermissions = await knex('permissions');
expect(storedPermissions).to.have.lengthOf(1);
});
});
describe('DELETE: `/roles/:id`', () => {
it('Should response not found in case the role was not exist.', async () => {
const res = await request().delete('/api/roles/100').send();
expect(res.status).equals(404);
});
it('Should not delete the predefined role.', async () => {
const role = await create('role', { predefined: true });
const res = await request().delete(`/api/roles/${role.id}`).send();
expect(res.status).equals(400);
});
it('Should delete the given role and its relations with permissions and resources.', async () => {
const role = await create('role');
await create('role_has_permission', { role_id: role.id });
await request().delete(`/api/roles/${role.id}`).send();
const storedRole = await knex('roles').where('id', role.id).first();
expect(storedRole).to.equals(undefined);
});
});
});

View File

@@ -2,35 +2,30 @@ import knex from '@/database/knex';
import {
request,
expect,
create,
make,
login,
} from '~/testInit';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: `/routes`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('GET: `/users`', () => {
it('Should response unauthorized if the user was not authorized.', async () => {
const res = await request().get('/api/users');
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should retrieve the stored users with pagination meta.', async () => {
await create('user');
await tenantFactory.create('user');
const res = await request()
.get('/api/users')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.users.results.length).equals(2);
@@ -38,205 +33,22 @@ describe('routes: `/routes`', () => {
});
});
describe('POST: `/users`', () => {
it('Should create a new user if the user was not authorized.', async () => {
const res = await request().post('/api/users');
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
});
it('Should `first_name` be required.', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
const foundFirstNameParam = res.body.errors.find((error) => error.param === 'first_name');
expect(!!foundFirstNameParam).equals(true);
});
it('Should `last_name` be required.', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
const foundFirstNameParam = res.body.errors.find((error) => error.param === 'last_name');
expect(!!foundFirstNameParam).equals(true);
});
it('Should `email` be required.', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
const foundEmailParam = res.body.errors.find((error) => error.param === 'email');
expect(!!foundEmailParam).equals(true);
});
it('Should be `email` be valid format.', async () => {
const user = make('user');
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
first_name: user.first_name,
last_name: user.last_name,
email: 'email',
phone_number: user.phone_number,
status: 1,
});
expect(res.status).equals(422);
const foundEmailParam = res.body.errors.find((error) => error.param === 'email');
expect(!!foundEmailParam).equals(true);
});
it('Should `phone_number` be valid format.', async () => {
const user = make('user');
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
phone_number: 'phone_number',
status: 1,
});
expect(res.status).equals(422);
const phoneNumberParam = res.body.errors.find((error) => error.param === 'phone_number');
expect(!!phoneNumberParam).equals(true);
});
it('Should `password` be required.', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
const passwordParam = res.body.errors.find((error) => error.param === 'password');
expect(!!passwordParam).equals(true);
});
it('Should password be equals confirm_password.', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
password: '123123',
});
expect(res.status).equals(422);
const passwordParam = res.body.errors.find((error) => error.param === 'password');
expect(!!passwordParam).equals(true);
});
it('Should `status` be boolean', async () => {
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
status: 'not_boolean',
});
expect(res.status).equals(422);
const statusParam = res.body.errors.find((error) => error.param === 'status');
expect(!!statusParam).equals(true);
});
it('Should response bad request in case email was already exist.', async () => {
const user = await create('user');
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
first_name: user.firstName,
last_name: user.lastName,
email: user.email,
phone_number: user.phoneNumber,
password: '123123123',
confirm_password: '123123123',
status: 1,
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'EMAIL_ALREADY_EXIST', code: 100,
});
});
it('Should response bad request in case phone number was already exist.', async () => {
const user = await create('user', { phone_number: '0927918381' });
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
first_name: user.firstName,
last_name: user.lastName,
email: user.email,
phone_number: '0927918381',
password: user.password,
confirm_password: user.password,
status: 1,
});
expect(res.status).equals(400);
expect(res.body.errors).include.something.that.deep.equals({
type: 'PHONE_NUMBER_ALREADY_EXIST', code: 120,
});
});
it('Should response success with correct data type.', async () => {
const user = await make('user', { phone_number: '0920000000' });
const res = await request()
.post('/api/users')
.set('x-access-token', loginRes.body.token)
.send({
first_name: user.firstName,
last_name: user.lastName,
email: user.email,
phone_number: '0920000000',
password: user.password,
confirm_password: user.password,
status: 1,
});
expect(res.status).equals(200);
expect(res.body.user.id).equals(2);
});
});
describe('POST: `/users/:id`', () => {
it('Should create a new user if the user was not authorized.', async () => {
const user = await create('user');
const res = await request().post(`/api/users/${user.id}`);
const user = await tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`);
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `first_name` be required.', async () => {
const user = await create('user');
const user = await  tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -246,10 +58,11 @@ describe('routes: `/routes`', () => {
});
it('Should `last_name` be required.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -259,10 +72,11 @@ describe('routes: `/routes`', () => {
});
it('Should `email` be required.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -272,10 +86,11 @@ describe('routes: `/routes`', () => {
});
it('Should be `email` be valid format.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
first_name: user.first_name,
last_name: user.last_name,
@@ -291,10 +106,11 @@ describe('routes: `/routes`', () => {
});
it('Should `phone_number` be valid format.', async () => {
const user = create('user');
const user = tenantFactory.create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
first_name: user.first_name,
last_name: user.last_name,
@@ -308,70 +124,32 @@ describe('routes: `/routes`', () => {
const phoneNumberParam = res.body.errors.find((error) => error.param === 'phone_number');
expect(!!phoneNumberParam).equals(true);
});
it('Should `password` be required.', async () => {
const user = create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.send();
expect(res.status).equals(422);
const passwordParam = res.body.errors.find((error) => error.param === 'password');
expect(!!passwordParam).equals(true);
});
it('Should password be equals confirm_password.', async () => {
const user = create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.send({
password: '123123',
});
expect(res.status).equals(422);
const passwordParam = res.body.errors.find((error) => error.param === 'password');
expect(!!passwordParam).equals(true);
});
it('Should `status` be boolean', async () => {
const user = create('user');
const res = await request()
.post(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.send({
status: 'not_boolean',
});
expect(res.status).equals(422);
const statusParam = res.body.errors.find((error) => error.param === 'status');
expect(!!statusParam).equals(true);
});
});
describe('GET: `/users/:id`', () => {
it('Should not success if the user was not authorized.', () => {
it('Should not success if the user was not authorized.', async () => {
const res = await request().get('/api/users/1');
expect(res.status).equals(401);
expect(res.body.message).equals('Unauthorized');
});
it('Should response not found if the user was not exist.', async () => {
const res = await request()
.get('/api/users/10')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
});
it('Should response success if the user was exist.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
const res = await request()
.get(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -379,14 +157,18 @@ describe('routes: `/routes`', () => {
});
describe('DELETE: `/users/:id`', () => {
it('Should not success if the user was not authorized.', () => {
it('Should not success if the user was not authorized.', async () => {
const res = await request().delete('/api/users/1');
expect(res.status).equals(401);
expect(res.body.message).equals('Unauthorized');
});
it('Should response not found if the user was not exist.', async () => {
const res = await request()
.delete('/api/users/10')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -396,20 +178,22 @@ describe('routes: `/routes`', () => {
});
it('Should response success if the user was exist.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
const res = await request()
.delete(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
});
it('Should delete the give user from the storage.', async () => {
const user = await create('user');
const user = await tenantFactory.create('user');
await request()
.delete(`/api/users/${user.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
const storedUsers = await knex('users').where('id', user.id);

View File

@@ -1,35 +1,30 @@
import {
request,
expect,
login,
create,
} from '~/testInit';
import View from '@/models/View';
import ViewRole from '@/models/ViewRole';
import '@/models/ResourceField';
import ViewColumn from '../../src/models/ViewColumn';
import {
tenantWebsite,
tenantFactory,
loginRes
} from '~/dbInit';
let loginRes;
describe('routes: `/views`', () => {
beforeEach(async () => {
loginRes = await login();
});
afterEach(() => {
loginRes = null;
});
describe('GET: `/views`', () => {
it('Should response unauthorized in case the user was not authorized.', async () => {
const res = await request().get('/api/views');
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should retrieve all views of the given resource name.', async () => {
const resource = await create('resource', { name: 'resource_name' });
const resourceFields = await create('view', {
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
const resourceFields = await tenantFactory.create('view', {
name: 'Resource View',
resource_id: resource.id,
roles_logic_expression: '',
@@ -38,6 +33,7 @@ describe('routes: `/views`', () => {
const res = await request()
.get('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.query({ resource_name: 'resource_name' })
.send();
@@ -48,8 +44,8 @@ describe('routes: `/views`', () => {
describe('GET `/views/:id`', () => {
it('Should response unauthorized in case the user was not authorized.', async () => {
const resource = await create('resource', { name: 'resource_name' });
const resourceView = await create('view', {
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
const resourceView = await tenantFactory.create('view', {
name: 'Resource View',
resource_id: resource.id,
roles_logic_expression: '',
@@ -61,12 +57,12 @@ describe('routes: `/views`', () => {
.send();
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should response not found in case the given view was not found.', async () => {
const resource = await create('resource', { name: 'resource_name' });
const resourceView = await create('view', {
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
const resourceView = await tenantFactory.create('view', {
name: 'Resource View',
resource_id: resource.id,
roles_logic_expression: '',
@@ -75,6 +71,7 @@ describe('routes: `/views`', () => {
const res = await request()
.get('/api/views/123')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -84,13 +81,13 @@ describe('routes: `/views`', () => {
});
it('Should retrieve details of the given view with associated graphs.', async () => {
const resource = await create('resource', { name: 'resource_name' });
const resourceView = await create('view', {
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
const resourceView = await tenantFactory.create('view', {
name: 'Resource View',
resource_id: resource.id,
roles_logic_expression: '1 AND 2',
});
const resourceField = await create('resource_field', {
const resourceField = await tenantFactory.create('resource_field', {
label_name: 'Expense Account',
key: 'expense_account',
data_type: 'integer',
@@ -99,7 +96,7 @@ describe('routes: `/views`', () => {
predefined: true,
builtin: true,
});
const viewRole = await create('view_role', {
const viewRole = await tenantFactory.create('view_role', {
view_id: resourceView.id,
index: 1,
field_id: resourceField.id,
@@ -110,6 +107,7 @@ describe('routes: `/views`', () => {
const res = await request()
.get(`/api/views/${resourceView.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(200);
@@ -127,14 +125,15 @@ describe('routes: `/views`', () => {
const res = await request().post('/api/views');
expect(res.status).equals(401);
expect(res.body.message).equals('unauthorized');
expect(res.body.message).equals('Unauthorized');
});
it('Should `name` be required.', async () => {
await create('resource');
await tenantFactory.create('resource');
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token);
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId);
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
@@ -144,10 +143,11 @@ describe('routes: `/views`', () => {
});
it('Should `resource_name` be required.', async () => {
await create('resource');
await tenantFactory.create('resource');
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token);
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId);
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
@@ -157,13 +157,14 @@ describe('routes: `/views`', () => {
});
it('Should `columns` be minimum limited', async () => {
await create('resource');
await tenantFactory.create('resource');
const res = await request()
.post('/api/views', {
label: 'View Label',
columns: [],
})
.set('x-access-token', loginRes.body.token);
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId);
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
@@ -173,13 +174,14 @@ describe('routes: `/views`', () => {
});
it('Should `columns` be array.', async () => {
await create('resource');
await tenantFactory.create('resource');
const res = await request()
.post('/api/views', {
label: 'View Label',
columns: 'not_array',
})
.set('x-access-token', loginRes.body.token);
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId);
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
@@ -189,10 +191,11 @@ describe('routes: `/views`', () => {
});
it('Should `roles.*.field_key` be required.', async () => {
const resource = await create('resource');
const resource = await tenantFactory.create('resource');
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
label: 'View Label',
@@ -207,10 +210,11 @@ describe('routes: `/views`', () => {
});
it('Should `roles.*.comparator` be valid.', async () => {
const resource = await create('resource');
const resource = await tenantFactory.create('resource');
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
label: 'View Label',
@@ -225,7 +229,7 @@ describe('routes: `/views`', () => {
});
it('Should `roles.*.index` be number as integer.', async () => {
const resource = await create('resource');
const resource = await tenantFactory.create('resource');
const res = await request()
.post('/api/views')
.send({
@@ -235,7 +239,8 @@ describe('routes: `/views`', () => {
{ index: 'not_numeric' },
],
})
.set('x-access-token', loginRes.body.token);
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId);
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
@@ -251,6 +256,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: 'not_found',
name: 'View Label',
@@ -275,8 +281,8 @@ describe('routes: `/views`', () => {
});
it('Should response invalid logic expression.', async () =>{
const resource = await create('resource');
await create('resource_field', {
const resource = await tenantFactory.create('resource');
await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
@@ -284,6 +290,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
logic_expression: '100 && 100',
@@ -305,12 +312,13 @@ describe('routes: `/views`', () => {
});
it('Should response the roles fields not exist in case role field was not exist.', async () => {
const resource = await create('resource');
await create('resource_field', { resource_id: resource.id, label_name: 'Amount' });
const resource = await tenantFactory.create('resource');
await tenantFactory.create('resource_field', { resource_id: resource.id, label_name: 'Amount' });
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
name: 'View Label',
@@ -334,8 +342,8 @@ describe('routes: `/views`', () => {
});
it('Should response the columns that not exists in case column was not exist.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
@@ -343,6 +351,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
name: 'View Label',
@@ -366,8 +375,8 @@ describe('routes: `/views`', () => {
});
it('Should save the given details of the view.', async () => {
const resource = await create('resource');
await create('resource_field', {
const resource = await tenantFactory.create('resource');
await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
@@ -375,6 +384,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
name: 'View Label',
@@ -390,7 +400,7 @@ describe('routes: `/views`', () => {
}],
});
const storedView = await View.query().where('name', 'View Label').first();
const storedView = await View.tenant().query().where('name', 'View Label').first();
expect(storedView.name).equals('View Label');
expect(storedView.predefined).equals(0);
@@ -398,8 +408,8 @@ describe('routes: `/views`', () => {
});
it('Should save the given details of view fields that associated to the given view id.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
@@ -408,6 +418,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
name: 'View Label',
@@ -421,7 +432,7 @@ describe('routes: `/views`', () => {
}],
});
const viewRoles = await ViewRole.query().where('view_id', res.body.id);
const viewRoles = await ViewRole.tenant().query().where('view_id', res.body.id);
expect(viewRoles.length).equals(1);
expect(viewRoles[0].index).equals(1);
@@ -431,8 +442,8 @@ describe('routes: `/views`', () => {
});
it('Should save columns that associated to the given view.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
@@ -441,6 +452,7 @@ describe('routes: `/views`', () => {
const res = await request()
.post('/api/views')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
resource_name: resource.name,
name: 'View Label',
@@ -456,7 +468,7 @@ describe('routes: `/views`', () => {
}],
});
const viewColumns = await ViewColumn.query().where('view_id', res.body.id);
const viewColumns = await ViewColumn.tenant().query().where('view_id', res.body.id);
expect(viewColumns.length).equals(1);
});
@@ -465,10 +477,11 @@ describe('routes: `/views`', () => {
describe('POST: `/views/:view_id`', () => {
it('Should `name` be required.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -479,13 +492,14 @@ describe('routes: `/views`', () => {
});
it('Should columns be minimum limited', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`, {
label: 'View Label',
columns: [],
})
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(422);
@@ -496,27 +510,31 @@ describe('routes: `/views`', () => {
});
it('Should columns be array.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`, {
label: 'View Label',
columns: 'not_array',
})
.set('x-access-token', loginRes.body.token)
.send();
.set('organization-id', tenantWebsite.organizationId)
.send({
columns: 'columns'
});
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'code', location: 'body',
msg: 'Invalid value', param: 'columns', location: 'body', value: 'columns',
});
});
it('Should `roles.*.field_key` be required.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
label: 'View Label',
roles: [{}],
@@ -525,15 +543,16 @@ describe('routes: `/views`', () => {
expect(res.status).equals(422);
expect(res.body.code).equals('validation_error');
expect(res.body.errors).include.something.deep.equals({
msg: 'Invalid value', param: 'roles', location: 'body',
msg: 'Invalid value', param: 'roles[0].field_key', location: 'body',
});
});
it('Should `roles.*.comparator` be required.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
label: 'View Label',
roles: [{}],
@@ -547,10 +566,11 @@ describe('routes: `/views`', () => {
});
it('Should `roles.*.index` be number as integer.', async () => {
const view = await create('view');
const view = await tenantFactory.create('view');
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
label: 'View Label',
roles: [{ index: 'not_numeric' }],
@@ -567,14 +587,15 @@ describe('routes: `/views`', () => {
});
it('Should response the roles fields not exist in case role field was not exist.', async () => {
const view = await create('view');
await create('resource_field', {
const view = await tenantFactory.create('view');
await tenantFactory.create('resource_field', {
resource_id: view.resource_id,
label_name: 'Amount',
});
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -601,14 +622,15 @@ describe('routes: `/views`', () => {
});
it('Should response the resource columns not exists in case the column keys was not exist.', async () => {
const view = await create('view');
await create('resource_field', {
const view = await tenantFactory.create('view');
await tenantFactory.create('resource_field', {
resource_id: view.resource_id,
label_name: 'Amount',
});
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -641,21 +663,22 @@ describe('routes: `/views`', () => {
});
it('Should delete the view roles that not presented the post data.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const viewRole = await create('view_role', {
const view = await tenantFactory.create('view', { resource_id: resource.id });
const viewRole = await tenantFactory.create('view_role', {
view_id: view.id,
field_id: resourceField.id,
});
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -671,26 +694,27 @@ describe('routes: `/views`', () => {
}],
});
const foundViewRole = await ViewRole.query().where('id', viewRole.id);
const foundViewRole = await ViewRole.tenant().query().where('id', viewRole.id);
expect(foundViewRole.length).equals(0);
});
it('Should update the view roles that presented in the given data.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const viewRole = await create('view_role', {
const view = await tenantFactory.create('view', { resource_id: resource.id });
const viewRole = await tenantFactory.create('view_role', {
view_id: view.id,
field_id: resourceField.id,
});
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -707,27 +731,28 @@ describe('routes: `/views`', () => {
}],
});
const foundViewRole = await ViewRole.query().where('id', viewRole.id);
const foundViewRole = await ViewRole.tenant().query().where('id', viewRole.id);
expect(foundViewRole.length).equals(1);
expect(foundViewRole[0].id).equals(1);
expect(foundViewRole[0].id).equals(viewRole.id);
expect(foundViewRole[0].index).equals(1);
expect(foundViewRole[0].value).equals('100');
expect(foundViewRole[0].comparator).equals('equals');
});
it('Should response not found roles ids in case not exists in the storage.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const view = await tenantFactory.create('view', { resource_id: resource.id });
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -750,18 +775,19 @@ describe('routes: `/views`', () => {
});
it('Should delete columns from storage in case view columns ids not presented.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const viewColumn = await create('view_column', { view_id: view.id });
const view = await tenantFactory.create('view', { resource_id: resource.id });
const viewColumn = await tenantFactory.create('view_column', { view_id: view.id });
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -778,22 +804,23 @@ describe('routes: `/views`', () => {
});
// console.log(res.status, res.body);
const foundViewColumns = await ViewColumn.query().where('id', viewColumn.id);
const foundViewColumns = await ViewColumn.tenant().query().where('id', viewColumn.id);
expect(foundViewColumns.length).equals(0);
});
it('Should insert columns to the storage if where new columns', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const view = await tenantFactory.create('view', { resource_id: resource.id });
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -809,7 +836,7 @@ describe('routes: `/views`', () => {
}],
});
const foundViewColumns = await ViewColumn.query().where('view_id', view.id);
const foundViewColumns = await ViewColumn.tenant().query().where('view_id', view.id);
expect(foundViewColumns.length).equals(1);
expect(foundViewColumns[0].viewId).equals(view.id);
@@ -819,18 +846,19 @@ describe('routes: `/views`', () => {
it('Should update columns on the storage.', async () => {
const resource = await create('resource');
const resourceField = await create('resource_field', {
const resource = await tenantFactory.create('resource');
const resourceField = await tenantFactory.create('resource_field', {
resource_id: resource.id,
label_name: 'Amount',
key: 'amount',
});
const view = await create('view', { resource_id: resource.id });
const viewColumn = await create('view_column', { view_id: view.id });
const view = await tenantFactory.create('view', { resource_id: resource.id });
const viewColumn = await tenantFactory.create('view_column', { view_id: view.id });
const res = await request()
.post(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send({
name: 'View Label',
logic_expression: '1',
@@ -849,7 +877,7 @@ describe('routes: `/views`', () => {
console.log(res.body)
const foundViewColumns = await ViewColumn.query().where('id', viewColumn.id);
const foundViewColumns = await ViewColumn.tenant().query().where('id', viewColumn.id);
expect(foundViewColumns.length).equals(1);
expect(foundViewColumns[0].id).equals(viewColumn.id);
@@ -861,10 +889,11 @@ describe('routes: `/views`', () => {
describe('DELETE: `/views/:resource_id`', () => {
it('Should not delete predefined view.', async () => {
const view = await create('view', { predefined: true });
const view = await tenantFactory.create('view', { predefined: true });
const res = await request()
.delete(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(400);
@@ -877,6 +906,7 @@ describe('routes: `/views`', () => {
const res = await request()
.delete('/api/views/100')
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.status).equals(404);
@@ -886,19 +916,20 @@ describe('routes: `/views`', () => {
});
it('Should delete the given view and associated view columns and roles.', async () => {
const view = await create('view', { predefined: false });
await create('view_role', { view_id: view.id });
await create('view_column', { view_id: view.id });
const view = await tenantFactory.create('view', { predefined: false });
await tenantFactory.create('view_role', { view_id: view.id });
await tenantFactory.create('view_column', { view_id: view.id });
const res = await request()
.delete(`/api/views/${view.id}`)
.set('x-access-token', loginRes.body.token)
.set('organization-id', tenantWebsite.organizationId)
.send();
expect(res.body.id).equals(view.id);
const foundViews = await View.query().where('id', view.id);
const foundViewRoles = await ViewRole.query().where('view_id', view.id);
const foundViews = await View.tenant().query().where('id', view.id);
const foundViewRoles = await ViewRole.tenant().query().where('view_id', view.id);
expect(foundViews).to.have.lengthOf(0);
expect(foundViewRoles).to.have.lengthOf(0);

View File

@@ -1,328 +0,0 @@
import { expect, create } from '~/testInit';
import JournalPoster from '@/services/Accounting/JournalPoster';
import JournalEntry from '@/services/Accounting/JournalEntry';
import AccountBalance from '@/models/AccountBalance';
import AccountTransaction from '@/models/AccountTransaction';
describe('JournalPoster', () => {
describe('credit()', () => {
it('Should write credit entry to journal entries stack.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
credit: 100,
account: 1,
});
journalEntries.credit(journalEntry);
expect(journalEntries.entries.length).equals(1);
});
});
describe('debit()', () => {
it('Should write debit entry to journal entries stack.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: 1,
});
journalEntries.debit(journalEntry);
expect(journalEntries.entries.length).equals(1);
});
});
describe('setBalanceChange()', () => {
it('Should increment balance amount after credit entry with credit normal account.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
credit: 100,
debit: 0,
account: 1,
accountNormal: 'debit',
});
journalEntries.credit(journalEntry);
expect(journalEntries.balancesChange).to.have.property(1, -100);
});
it('Should decrement balance amount after debit entry wiht debit normal account.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: 1,
accountNormal: 'debit',
});
journalEntries.debit(journalEntry);
expect(journalEntries.balancesChange).to.have.property(1, 100);
});
});
describe('saveEntries()', () => {
it('Should save all stacked entries to the storage.', async () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: 1,
accountNormal: 'debit',
});
journalEntries.debit(journalEntry);
await journalEntries.saveEntries();
const storedJournalEntries = await AccountTransaction.query();
expect(storedJournalEntries.length).equals(1);
expect(storedJournalEntries[0]).to.deep.include({
referenceType: 'Expense',
referenceId: 1,
debit: 100,
credit: 0,
accountId: 1,
});
});
});
describe('saveBalance()', () => {
it('Should save account balance increment.', async () => {
const account = await create('account');
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: account.id,
accountNormal: 'debit',
});
journalEntries.debit(journalEntry);
await journalEntries.saveBalance();
const storedAccountBalance = await AccountBalance.query();
expect(storedAccountBalance.length).equals(1);
expect(storedAccountBalance[0].amount).equals(100);
});
it('Should save account balance decrement.', async () => {
const account = await create('account');
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
credit: 100,
account: account.id,
accountNormal: 'debit',
});
journalEntries.credit(journalEntry);
await journalEntries.saveBalance();
const storedAccountBalance = await AccountBalance.query();
expect(storedAccountBalance.length).equals(1);
expect(storedAccountBalance[0].amount).equals(-100);
});
});
describe('getClosingBalance', () => {
it('Should retrieve closing balance the given account id.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: 1,
accountNormal: 'debit',
date: '2020-1-10',
});
const journalEntry2 = new JournalEntry({
referenceId: 1,
referenceType: 'Income',
credit: 100,
account: 2,
accountNormal: 'credit',
date: '2020-1-12',
});
journalEntries.credit(journalEntry);
journalEntries.credit(journalEntry2);
const closingBalance = journalEntries.getClosingBalance(1, '2020-1-30');
expect(closingBalance).equals(100);
});
it('Should retrieve closing balance the given closing date period.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 100,
account: 1,
accountNormal: 'debit',
date: '2020-1-10',
});
const journalEntry2 = new JournalEntry({
referenceId: 1,
referenceType: 'Income',
credit: 100,
account: 2,
accountNormal: 'credit',
date: '2020-1-12',
});
journalEntries.credit(journalEntry);
journalEntries.credit(journalEntry2);
const closingBalance = journalEntries.getClosingBalance(1, '2020-1-2');
expect(closingBalance).equals(0);
});
});
describe('getTrialBalance(account, closeDate, dateType)', () => {
it('Should retrieve the trial balance of the given account id.', () => {
const journalEntries = new JournalPoster();
const journalEntry = new JournalEntry({
referenceId: 1,
referenceType: 'Expense',
debit: 200,
account: 1,
accountNormal: 'debit',
date: '2020-1-10',
});
const journalEntry2 = new JournalEntry({
referenceId: 1,
referenceType: 'Income',
credit: 100,
account: 1,
accountNormal: 'credit',
date: '2020-1-12',
});
journalEntries.debit(journalEntry);
journalEntries.credit(journalEntry2);
const trialBalance = journalEntries.getTrialBalance(1);
expect(trialBalance.credit).equals(100);
expect(trialBalance.debit).equals(200);
});
});
describe('groupingEntriesByDate(accountId, dateGroupType)', () => {
});
describe('removeEntries', () => {
it('Should remove all entries in the collection.', () => {
const journalPoster = new JournalPoster();
const journalEntry1 = new JournalEntry({
id: 1,
credit: 1000,
account: 1,
accountNormal: 'credit',
});
const journalEntry2 = new JournalEntry({
id: 2,
debit: 1000,
account: 2,
accountNormal: 'debit',
});
journalPoster.credit(journalEntry1);
journalPoster.debit(journalEntry2);
journalPoster.removeEntries();
expect(journalPoster.entries.length).equals(0);
});
it('Should remove the given entries ids from the collection.', () => {
const journalPoster = new JournalPoster();
const journalEntry1 = new JournalEntry({
id: 1,
credit: 1000,
account: 1,
accountNormal: 'credit',
});
const journalEntry2 = new JournalEntry({
id: 2,
debit: 1000,
account: 2,
accountNormal: 'debit',
});
journalPoster.credit(journalEntry1);
journalPoster.debit(journalEntry2);
journalPoster.removeEntries([1]);
expect(journalPoster.entries.length).equals(1);
});
it('Should the removed entries ids be stacked to deleted entries ids.', () => {
const journalPoster = new JournalPoster();
const journalEntry1 = new JournalEntry({
id: 1,
credit: 1000,
account: 1,
accountNormal: 'credit',
});
const journalEntry2 = new JournalEntry({
id: 2,
debit: 1000,
account: 2,
accountNormal: 'debit',
});
journalPoster.credit(journalEntry1);
journalPoster.debit(journalEntry2);
journalPoster.removeEntries();
expect(journalPoster.deletedEntriesIds.length).equals(2);
expect(journalPoster.deletedEntriesIds[0]).equals(1);
expect(journalPoster.deletedEntriesIds[1]).equals(2);
});
it('Should revert the account balance after remove the entries.', () => {
const journalPoster = new JournalPoster();
const journalEntry1 = new JournalEntry({
id: 1,
credit: 1000,
account: 1,
accountNormal: 'credit',
});
const journalEntry2 = new JournalEntry({
id: 2,
debit: 1000,
account: 2,
accountNormal: 'debit',
});
journalPoster.credit(journalEntry1);
journalPoster.debit(journalEntry2);
journalPoster.removeEntries([1]);
expect(journalPoster.balancesChange['1']).equals(0);
expect(journalPoster.balancesChange['2']).equals(1000);
})
});
describe('deleteEntries', () => {
it('Should delete all entries from the storage based on the stacked deleted entries ids.', () => {
});
});
describe('reverseEntries()', () => {
});
describe('loadFromCollection', () => {
});
});

View File

@@ -1,54 +1,88 @@
import chai from 'chai';
import chaiHttp from 'chai-http';
import chaiThings from 'chai-things';
import knex from '@/database/knex';
import '@/models';
import systemDb from '@/database/knex';
import app from '@/app';
import factory from '@/database/factories';
import dbManager from '@/database/manager';
// import { hashPassword } from '@/utils';
import createTenantFactory from '@/database/factories';
import TenantsManager from '@/system/TenantsManager';
import faker from 'faker';
import { hashPassword } from '@/utils';
import TenantModel from '@/models/TenantModel';
import createSystemFactory from '@/database/factories/system';
const request = () => chai.request(app);
const { expect } = chai;
const login = async (givenUser) => {
const user = !givenUser ? await factory.create('user') : givenUser;
const response = request()
.post('/api/auth/login')
.send({
crediential: user.email,
password: 'admin',
});
return response;
};
before(async () => {
await dbManager.closeKnex();
await dbManager.close();
// await dbManager.dropDb();
// await dbManager.createDb();
});
const request = () => chai.request(app);
beforeEach(async () => {
await knex.migrate.rollback();
await knex.migrate.latest();
// Rollback/migrate the system database.
await systemDb.migrate.rollback();
await systemDb.migrate.latest();
});
after(async () => {
afterEach(async () => {
});
chai.use(chaiHttp);
chai.use(chaiThings);
const create = async (name, data) => factory.create(name, data);
const make = async (name, data) => factory.build(name, data);
// Create tenant database.
const createTenant = () => {
return TenantsManager.createTenant();
};
// Drops tenant database.
const dropTenant = async (tenantWebsite) => {
return TenantsManager.dropTenant(tenantWebsite);
};
// Create a new user that associate to the given tenant Db.
const createUser = async (tenantWebsite, givenUser) => {
const userPassword = (givenUser && givenUser.password) ? givenUser.password : 'admin'
const hashedPassword = await hashPassword(userPassword);
const userInfo = {
first_name: faker.lorem.word(),
last_name: faker.lorem.word(),
email: faker.internet.email(),
active: 1,
phone_number: faker.phone.phoneNumberFormat().replace('-', ''),
password: hashedPassword,
...givenUser,
};
const user = await TenantsManager.createTenantUser(tenantWebsite, userInfo);
return user;
};
const login = async (tenantWebsite, givenUser) => {
let user = givenUser;
if (!givenUser && tenantWebsite) {
const createdUser = await createUser(tenantWebsite, givenUser);
user = createdUser;
}
return request()
.post('/api/auth/login')
.send({
crediential: user.email,
password: 'admin',
});
};
const bindTenantModel = (tenantDb) => {
TenantModel.knexBinded = tenantDb;
};
const systemFactory = createSystemFactory();
export {
login,
create,
make,
systemFactory,
createTenantFactory,
createTenant,
createUser,
dropTenant,
expect,
request,
bindTenantModel,
};