mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
672 lines
21 KiB
JavaScript
672 lines
21 KiB
JavaScript
import {
|
|
request,
|
|
create,
|
|
expect,
|
|
login,
|
|
} from '~/testInit';
|
|
import knex from '@/database/knex';
|
|
import Item from '@/models/Item';
|
|
|
|
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()
|
|
.post('/api/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);
|
|
});
|
|
|
|
it('Should `name` be required.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.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: 'name', location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `type` be required.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.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: 'type', location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `type` be one of defined words.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
type: 'not-defined',
|
|
});
|
|
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not-defined',
|
|
msg: 'Invalid value',
|
|
param: 'type',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `buy_price` be numeric.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
cost_price: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'cost_price',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `sell_price` be numeric.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
sell_price: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'sell_price',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `sell_account_id` be integer.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
cost_account_id: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'cost_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `cost_account_id` be integer.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
sell_account_id: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'sell_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `cost_account_id` be required if `cost_price` was presented.', async () => {
|
|
|
|
});
|
|
|
|
it('Should `buy_account_id` be required if `buy_price` was presented.', async () => {
|
|
|
|
});
|
|
|
|
it('Should `inventory_account_id` be required if type was `inventory` item.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'inventory',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
msg: 'Invalid value',
|
|
param: 'inventory_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `inventory_account_id` be not required if type was not `inventory`.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.body.errors).include.something.deep.not.equals({
|
|
msg: 'Invalid value',
|
|
param: 'inventory_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should response bad request in case `cost account` was not exist.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.status).equals(400);
|
|
expect(res.body.errors).include.something.that.deep.equals({
|
|
type: 'COST_ACCOUNT_NOT_FOUND', code: 100,
|
|
});
|
|
});
|
|
|
|
it('Should response bad request in case sell account was not exist.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.status).equals(400);
|
|
expect(res.body.errors).include.something.that.deep.equals({
|
|
type: 'SELL_ACCOUNT_NOT_FOUND', code: 120,
|
|
});
|
|
});
|
|
|
|
it('Should response not category found in case item category was not exist.', async () => {
|
|
const res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
category_id: 20,
|
|
});
|
|
|
|
expect(res.status).equals(400);
|
|
expect(res.body.errors).include.something.that.deep.equals({
|
|
type: 'ITEM_CATEGORY_NOT_FOUND', code: 140,
|
|
});
|
|
});
|
|
|
|
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 res = await request()
|
|
.post('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: account.id,
|
|
cost_account_id: anotherAccount.id,
|
|
category_id: itemCategory.id,
|
|
});
|
|
|
|
expect(res.status).equals(200);
|
|
});
|
|
});
|
|
|
|
describe('POST: `items/:id`', () => {
|
|
it('Should response item not found in case item id was not exist.', async () => {
|
|
const res = await request()
|
|
.post('/api/items/100')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'product',
|
|
cost_price: 100,
|
|
sell_price: 200,
|
|
sell_account_id: 1,
|
|
cost_account_id: 2,
|
|
category_id: 2,
|
|
});
|
|
|
|
expect(res.status).equals(404);
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
type: 'ITEM.NOT.FOUND', code: 100,
|
|
});
|
|
});
|
|
|
|
it('Should `name` be required.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.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: 'name', location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `type` be required.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.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: 'type', location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `sell_price` be numeric.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
sell_price: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'sell_price',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `cost_price` be numeric.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
cost_price: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'cost_price',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `sell_account_id` be integer.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
sell_account_id: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'sell_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should `cost_account_id` be integer.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
cost_account_id: 'not_numeric',
|
|
});
|
|
|
|
expect(res.status).equals(422);
|
|
expect(res.body.code).equals('validation_error');
|
|
expect(res.body.errors).include.something.deep.equals({
|
|
value: 'not_numeric',
|
|
msg: 'Invalid value',
|
|
param: 'cost_account_id',
|
|
location: 'body',
|
|
});
|
|
});
|
|
|
|
it('Should response bad request in case cost account was not exist.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.status).equals(400);
|
|
expect(res.body.errors).include.something.that.deep.equals({
|
|
type: 'COST_ACCOUNT_NOT_FOUND', code: 100,
|
|
});
|
|
});
|
|
|
|
it('Should response bad request in case sell account was not exist.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'Item Name',
|
|
type: 'product',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: 10,
|
|
cost_account_id: 20,
|
|
});
|
|
|
|
expect(res.status).equals(400);
|
|
expect(res.body.errors).include.something.that.deep.equals({
|
|
type: 'SELL_ACCOUNT_NOT_FOUND', code: 120,
|
|
});
|
|
});
|
|
|
|
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 item = await create('item');
|
|
const res = await request()
|
|
.post(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send({
|
|
name: 'New Item Name',
|
|
type: 'service',
|
|
sell_price: 10.2,
|
|
cost_price: 20.2,
|
|
sell_account_id: account.id,
|
|
cost_account_id: anotherAccount.id,
|
|
category_id: itemCategory.id,
|
|
});
|
|
|
|
const updatedItem = await Item.query().findById(item.id);
|
|
|
|
expect(updatedItem.name).equals('New Item Name');
|
|
expect(updatedItem.type).equals('service');
|
|
expect(updatedItem.sellPrice).equals(10.2);
|
|
expect(updatedItem.costPrice).equals(20.2);
|
|
expect(updatedItem.sellAccountId).equals(account.id);
|
|
expect(updatedItem.costAccountId).equals(anotherAccount.id);
|
|
expect(updatedItem.categoryId).equals(itemCategory.id);
|
|
});
|
|
});
|
|
|
|
describe('DELETE: `items/:id`', () => {
|
|
it('Should response not found in case the item was not exist.', async () => {
|
|
const res = await request()
|
|
.delete('/api/items/10')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send();
|
|
|
|
expect(res.status).equals(404);
|
|
});
|
|
|
|
it('Should response success in case was exist.', async () => {
|
|
const item = await create('item');
|
|
const res = await request()
|
|
.delete(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send();
|
|
|
|
expect(res.status).equals(200);
|
|
});
|
|
|
|
it('Should delete the given item from the storage.', async () => {
|
|
const item = await create('item');
|
|
await request()
|
|
.delete(`/api/items/${item.id}`)
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send();
|
|
|
|
const storedItems = await Item.query().where('id', item.id);
|
|
expect(storedItems).to.have.lengthOf(0);
|
|
});
|
|
});
|
|
|
|
describe('GET: `items`', () => {
|
|
it('Should response unauthorized access in case the user not authenticated.', async () => {
|
|
const res = await request()
|
|
.get('/api/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,
|
|
});
|
|
});
|
|
|
|
it('Should retrieve items list with associated accounts.', async () => {
|
|
await create('resource', { name: 'items' });
|
|
await create('item');
|
|
|
|
const res = await request()
|
|
.get('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send();
|
|
|
|
expect(res.status).equals(200);
|
|
|
|
expect(res.body.items).to.be.a('object');
|
|
expect(res.body.items.results).to.be.a('array');
|
|
expect(res.body.items.results.length).equals(1);
|
|
|
|
expect(res.body.items.results[0].cost_account).to.be.an('object');
|
|
expect(res.body.items.results[0].sell_account).to.be.an('object');
|
|
expect(res.body.items.results[0].inventory_account).to.be.an('object');
|
|
expect(res.body.items.results[0].category).to.be.an('object');
|
|
});
|
|
|
|
it('Should retrieve ordered items based on the given `column_sort_order` and `sort_order` query.', async () => {
|
|
await create('resource', { name: 'items' });
|
|
await create('item', { name: 'ahmed' });
|
|
await create('item', { name: 'mohamed' });
|
|
|
|
const res = await request()
|
|
.get('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.query({
|
|
column_sort_order: 'name',
|
|
sort_order: 'desc',
|
|
})
|
|
.send();
|
|
|
|
expect(res.body.items.results.length).equals(2);
|
|
expect(res.body.items.results[0].name).equals('mohamed');
|
|
expect(res.body.items.results[1].name).equals('ahmed');
|
|
});
|
|
|
|
it('Should retrieve pagination meta of items list.', async () => {
|
|
await create('resource', { name: 'items' });
|
|
|
|
const res = await request()
|
|
.get('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.send();
|
|
|
|
expect(res.body.items.results).to.be.a('array');
|
|
expect(res.body.items.results.length).equals(0);
|
|
expect(res.body.items.pagination).to.be.a('object');
|
|
expect(res.body.items.pagination.total).to.be.a('number');
|
|
expect(res.body.items.pagination.total).equals(0)
|
|
});
|
|
|
|
it('Should retrieve filtered items based on custom view conditions.', async () => {
|
|
const resource = await create('resource', { name: 'items' });
|
|
const resourceField = await create('resource_field', {
|
|
label_name: 'Type',
|
|
key: 'type',
|
|
resource_id: resource.id,
|
|
});
|
|
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 view = await create('view', {
|
|
name: 'Items Inventory',
|
|
resource_id: resource.id,
|
|
roles_logic_expression: '1',
|
|
});
|
|
const viewCondition = await create('view_role', {
|
|
view_id: view.id,
|
|
index: 1,
|
|
field_id: resourceField,
|
|
value: 'inventory',
|
|
comparator: 'equals',
|
|
});
|
|
const res = await request()
|
|
.get('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.query({
|
|
custom_view_id: view.id,
|
|
})
|
|
.send();
|
|
|
|
expect(res.body.customViewId).equals(view.id);
|
|
expect(res.body.viewColumns).to.be.a('array');
|
|
expect(res.body.viewConditions).to.be.a('array');
|
|
expect(res.body.items.results.length).equals(2);
|
|
expect(res.body.items.results[0].type).equals('inventory');
|
|
expect(res.body.items.results[1].type).equals('inventory');
|
|
});
|
|
|
|
it('Should retrieve filtered items based on filtering conditions.', async () => {
|
|
const resource = await create('resource', { name: 'items' });
|
|
const resourceField = await create('resource_field', {
|
|
label_name: 'Type',
|
|
key: 'type',
|
|
resource_id: resource.id,
|
|
});
|
|
const resourceNameField = await create('resource_field', {
|
|
label_name: 'item name',
|
|
key: 'name',
|
|
resource_id: resource.id,
|
|
});
|
|
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 res = await request()
|
|
.get('/api/items')
|
|
.set('x-access-token', loginRes.body.token)
|
|
.query({
|
|
stringified_filter_roles: JSON.stringify([
|
|
{
|
|
condition: '&&',
|
|
field_key: 'type',
|
|
comparator: 'equals',
|
|
value: 'inventory',
|
|
},
|
|
{
|
|
condition: '||',
|
|
field_key: 'name',
|
|
comparator: 'equals',
|
|
value: 'target',
|
|
},
|
|
]),
|
|
})
|
|
.send();
|
|
|
|
expect(res.body.items.results.length).equals(3);
|
|
expect(res.body.items.results[0].name).equals('target');
|
|
expect(res.body.items.results[1].type).equals('inventory');
|
|
expect(res.body.items.results[2].type).equals('inventory');
|
|
});
|
|
});
|
|
});
|