mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
WIP pass the failed tests.
This commit is contained in:
425
common/routes/users.test.js
Normal file
425
common/routes/users.test.js
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
import knex from '@/database/knex';
|
||||||
|
import {
|
||||||
|
request,
|
||||||
|
expect,
|
||||||
|
create,
|
||||||
|
make,
|
||||||
|
login,
|
||||||
|
createTenantFactory,
|
||||||
|
createTenant,
|
||||||
|
} from '~/testInit';
|
||||||
|
|
||||||
|
let tenantDb;
|
||||||
|
let tenantFactory;
|
||||||
|
|
||||||
|
describe.only('routes: `/routes`', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
tenantDb = await createTenant();
|
||||||
|
tenantFactory = createTenantFactory(tenantDb);
|
||||||
|
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should retrieve the stored users with pagination meta.', async () => {
|
||||||
|
await create('user');
|
||||||
|
|
||||||
|
const res = await request()
|
||||||
|
.get('/api/users')
|
||||||
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.body.users.results.length).equals(2);
|
||||||
|
expect(res.body.users.total).equals(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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}`);
|
||||||
|
|
||||||
|
expect(res.status).equals(401);
|
||||||
|
expect(res.body.message).equals('unauthorized');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should `first_name` be required.', async () => {
|
||||||
|
const user = await 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 foundFirstNameParam = res.body.errors.find((error) => error.param === 'first_name');
|
||||||
|
expect(!!foundFirstNameParam).equals(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should `last_name` be required.', async () => {
|
||||||
|
const user = await 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 foundFirstNameParam = res.body.errors.find((error) => error.param === 'last_name');
|
||||||
|
expect(!!foundFirstNameParam).equals(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should `email` be required.', async () => {
|
||||||
|
const user = await 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 foundEmailParam = res.body.errors.find((error) => error.param === 'email');
|
||||||
|
expect(!!foundEmailParam).equals(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be `email` be valid format.', async () => {
|
||||||
|
const user = await create('user');
|
||||||
|
const res = await request()
|
||||||
|
.post(`/api/users/${user.id}`)
|
||||||
|
.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 = create('user');
|
||||||
|
const res = await request()
|
||||||
|
.post(`/api/users/${user.id}`)
|
||||||
|
.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 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 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)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).equals(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should response success if the user was exist.', async () => {
|
||||||
|
const user = await create('user');
|
||||||
|
const res = await request()
|
||||||
|
.get(`/api/users/${user.id}`)
|
||||||
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).equals(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DELETE: `/users/:id`', () => {
|
||||||
|
it('Should not success if the user was not authorized.', () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
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)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).equals(404);
|
||||||
|
expect(res.body.errors).include.something.that.deep.equals({
|
||||||
|
type: 'USER_NOT_FOUND', code: 100,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should response success if the user was exist.', async () => {
|
||||||
|
const user = await create('user');
|
||||||
|
const res = await request()
|
||||||
|
.delete(`/api/users/${user.id}`)
|
||||||
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).equals(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should delete the give user from the storage.', async () => {
|
||||||
|
const user = await create('user');
|
||||||
|
await request()
|
||||||
|
.delete(`/api/users/${user.id}`)
|
||||||
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
const storedUsers = await knex('users').where('id', user.id);
|
||||||
|
expect(storedUsers).to.have.lengthOf(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -12,6 +12,7 @@ const configEnv = {
|
|||||||
migrations: {
|
migrations: {
|
||||||
directory: config.system.migrations_dir,
|
directory: config.system.migrations_dir,
|
||||||
},
|
},
|
||||||
|
pool: { min: 0, max: 7 },
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -1,282 +1,284 @@
|
|||||||
import knexFactory from 'knex-factory';
|
import KnexFactory from '@/lib/KnexFactory';
|
||||||
import faker from 'faker';
|
import faker from 'faker';
|
||||||
import knex from '@/database/knex';
|
|
||||||
import { hashPassword } from '@/utils';
|
import { hashPassword } from '@/utils';
|
||||||
|
|
||||||
const factory = knexFactory(knex);
|
|
||||||
|
|
||||||
factory.define('user', 'users', async () => {
|
export default (tenantDb) => {
|
||||||
const hashedPassword = await hashPassword('admin');
|
const factory = new KnexFactory(tenantDb);
|
||||||
return {
|
|
||||||
first_name: faker.name.firstName(),
|
|
||||||
last_name: faker.name.lastName(),
|
|
||||||
email: faker.internet.email(),
|
|
||||||
phone_number: faker.phone.phoneNumberFormat().replace('-', ''),
|
|
||||||
active: 1,
|
|
||||||
password: hashedPassword,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('password_reset', 'password_resets', async () => {
|
factory.define('user', 'users', async () => {
|
||||||
const user = await faker.create('user');
|
// const hashedPassword = await hashPassword('admin');
|
||||||
return {
|
|
||||||
user_id: user.id,
|
|
||||||
token: faker.lorem.slug,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('account_type', 'account_types', async () => ({
|
return {
|
||||||
name: faker.lorem.words(2),
|
first_name: faker.name.firstName(),
|
||||||
normal: 'debit',
|
last_name: faker.name.lastName(),
|
||||||
}));
|
email: faker.internet.email(),
|
||||||
|
phone_number: faker.phone.phoneNumberFormat().replace('-', ''),
|
||||||
|
active: 1,
|
||||||
|
// password: hashedPassword,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
factory.define('account_balance', 'account_balances', async () => {
|
factory.define('password_reset', 'password_resets', async () => {
|
||||||
const account = await factory.create('account');
|
return {
|
||||||
|
user_id: null,
|
||||||
|
token: faker.lorem.slug,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
factory.define('account_type', 'account_types', async () => ({
|
||||||
account_id: account.id,
|
name: faker.lorem.words(2),
|
||||||
amount: faker.random.number(),
|
normal: 'debit',
|
||||||
currency_code: 'USD',
|
}));
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('account', 'accounts', async () => {
|
factory.define('account_balance', 'account_balances', async () => {
|
||||||
const accountType = await factory.create('account_type');
|
const account = await factory.create('account');
|
||||||
return {
|
|
||||||
|
return {
|
||||||
|
account_id: account.id,
|
||||||
|
amount: faker.random.number(),
|
||||||
|
currency_code: 'USD',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('account', 'accounts', async () => {
|
||||||
|
const accountType = await factory.create('account_type');
|
||||||
|
return {
|
||||||
|
name: faker.lorem.word(),
|
||||||
|
code: faker.random.number(),
|
||||||
|
account_type_id: accountType.id,
|
||||||
|
description: faker.lorem.paragraph(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('account_transaction', 'accounts_transactions', async () => {
|
||||||
|
const account = await factory.create('account');
|
||||||
|
const user = await factory.create('user');
|
||||||
|
|
||||||
|
return {
|
||||||
|
account_id: account.id,
|
||||||
|
credit: faker.random.number(),
|
||||||
|
debit: 0,
|
||||||
|
user_id: user.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('manual_journal', 'manual_journals', async () => {
|
||||||
|
const user = await factory.create('user');
|
||||||
|
|
||||||
|
return {
|
||||||
|
journal_number: faker.random.number(),
|
||||||
|
transaction_type: '',
|
||||||
|
amount: faker.random.number(),
|
||||||
|
date: faker.date.future,
|
||||||
|
status: 1,
|
||||||
|
user_id: user.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('item_category', 'items_categories', () => ({
|
||||||
|
name: faker.name.firstName(),
|
||||||
|
description: faker.lorem.text(),
|
||||||
|
parent_category_id: null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
factory.define('item_metadata', 'items_metadata', async () => {
|
||||||
|
const item = await factory.create('item');
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: faker.lorem.slug(),
|
||||||
|
value: faker.lorem.word(),
|
||||||
|
item_id: item.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('item', 'items', async () => {
|
||||||
|
const category = await factory.create('item_category');
|
||||||
|
const costAccount = await factory.create('account');
|
||||||
|
const sellAccount = await factory.create('account');
|
||||||
|
const inventoryAccount = await factory.create('account');
|
||||||
|
return {
|
||||||
|
name: faker.lorem.word(),
|
||||||
|
note: faker.lorem.paragraph(),
|
||||||
|
cost_price: faker.random.number(),
|
||||||
|
sell_price: faker.random.number(),
|
||||||
|
cost_account_id: costAccount.id,
|
||||||
|
sell_account_id: sellAccount.id,
|
||||||
|
inventory_account_id: inventoryAccount.id,
|
||||||
|
category_id: category.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('setting', 'settings', async () => {
|
||||||
|
const user = await factory.create('user');
|
||||||
|
return {
|
||||||
|
key: faker.lorem.slug(),
|
||||||
|
user_id: user.id,
|
||||||
|
type: 'string',
|
||||||
|
value: faker.lorem.words(),
|
||||||
|
group: 'default',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('role', 'roles', async () => ({
|
||||||
name: faker.lorem.word(),
|
name: faker.lorem.word(),
|
||||||
code: faker.random.number(),
|
description: faker.lorem.words(),
|
||||||
account_type_id: accountType.id,
|
|
||||||
description: faker.lorem.paragraph(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('account_transaction', 'accounts_transactions', async () => {
|
|
||||||
const account = await factory.create('account');
|
|
||||||
const user = await factory.create('user');
|
|
||||||
|
|
||||||
return {
|
|
||||||
account_id: account.id,
|
|
||||||
credit: faker.random.number(),
|
|
||||||
debit: 0,
|
|
||||||
user_id: user.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('manual_journal', 'manual_journals', async () => {
|
|
||||||
const user = await factory.create('user');
|
|
||||||
|
|
||||||
return {
|
|
||||||
journal_number: faker.random.number(),
|
|
||||||
transaction_type: '',
|
|
||||||
amount: faker.random.number(),
|
|
||||||
date: faker.date.future,
|
|
||||||
status: 1,
|
|
||||||
user_id: user.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('item_category', 'items_categories', () => ({
|
|
||||||
name: faker.name.firstName(),
|
|
||||||
description: faker.lorem.text(),
|
|
||||||
parent_category_id: null,
|
|
||||||
}));
|
|
||||||
|
|
||||||
factory.define('item_metadata', 'items_metadata', async () => {
|
|
||||||
const item = await factory.create('item');
|
|
||||||
|
|
||||||
return {
|
|
||||||
key: faker.lorem.slug(),
|
|
||||||
value: faker.lorem.word(),
|
|
||||||
item_id: item.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('item', 'items', async () => {
|
|
||||||
const category = await factory.create('item_category');
|
|
||||||
const costAccount = await factory.create('account');
|
|
||||||
const sellAccount = await factory.create('account');
|
|
||||||
const inventoryAccount = await factory.create('account');
|
|
||||||
return {
|
|
||||||
name: faker.lorem.word(),
|
|
||||||
note: faker.lorem.paragraph(),
|
|
||||||
cost_price: faker.random.number(),
|
|
||||||
sell_price: faker.random.number(),
|
|
||||||
cost_account_id: costAccount.id,
|
|
||||||
sell_account_id: sellAccount.id,
|
|
||||||
inventory_account_id: inventoryAccount.id,
|
|
||||||
category_id: category.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('setting', 'settings', async () => {
|
|
||||||
const user = await factory.create('user');
|
|
||||||
return {
|
|
||||||
key: faker.lorem.slug(),
|
|
||||||
user_id: user.id,
|
|
||||||
type: 'string',
|
|
||||||
value: faker.lorem.words(),
|
|
||||||
group: 'default',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('role', 'roles', async () => ({
|
|
||||||
name: faker.lorem.word(),
|
|
||||||
description: faker.lorem.words(),
|
|
||||||
predefined: false,
|
|
||||||
}));
|
|
||||||
|
|
||||||
factory.define('user_has_role', 'user_has_roles', async () => {
|
|
||||||
const user = await factory.create('user');
|
|
||||||
const role = await factory.create('role');
|
|
||||||
|
|
||||||
return {
|
|
||||||
user_id: user.id,
|
|
||||||
role_id: role.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('permission', 'permissions', async () => {
|
|
||||||
const permissions = ['create', 'edit', 'delete', 'view', 'owner'];
|
|
||||||
const randomPermission = permissions[Math.floor(Math.random() * permissions.length)];
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: randomPermission,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('role_has_permission', 'role_has_permissions', async () => {
|
|
||||||
const permission = await factory.create('permission');
|
|
||||||
const role = await factory.create('role');
|
|
||||||
const resource = await factory.create('resource');
|
|
||||||
|
|
||||||
return {
|
|
||||||
role_id: role.id,
|
|
||||||
permission_id: permission.id,
|
|
||||||
resource_id: resource.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('resource', 'resources', () => ({
|
|
||||||
name: faker.lorem.word(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
factory.define('view', 'views', async () => {
|
|
||||||
const resource = await factory.create('resource');
|
|
||||||
return {
|
|
||||||
name: faker.lorem.word(),
|
|
||||||
resource_id: resource.id,
|
|
||||||
predefined: false,
|
predefined: false,
|
||||||
};
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('resource_field', 'resource_fields', async () => {
|
factory.define('user_has_role', 'user_has_roles', async () => {
|
||||||
const resource = await factory.create('resource');
|
const user = await factory.create('user');
|
||||||
const dataTypes = ['select', 'date', 'text'];
|
const role = await factory.create('role');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label_name: faker.lorem.words(),
|
user_id: user.id,
|
||||||
key: faker.lorem.slug(),
|
role_id: role.id,
|
||||||
data_type: dataTypes[Math.floor(Math.random() * dataTypes.length)],
|
};
|
||||||
help_text: faker.lorem.words(),
|
});
|
||||||
default: faker.lorem.word(),
|
|
||||||
resource_id: resource.id,
|
|
||||||
active: true,
|
|
||||||
columnable: true,
|
|
||||||
predefined: false,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('resource_custom_field_metadata', 'resource_custom_fields_metadata', async () => {
|
factory.define('permission', 'permissions', async () => {
|
||||||
const resource = await factory.create('resource');
|
const permissions = ['create', 'edit', 'delete', 'view', 'owner'];
|
||||||
|
const randomPermission = permissions[Math.floor(Math.random() * permissions.length)];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
resource_id: resource.id,
|
name: randomPermission,
|
||||||
resource_item_id: 1,
|
};
|
||||||
key: faker.lorem.words(),
|
});
|
||||||
value: faker.lorem.words(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('view_role', 'view_roles', async () => {
|
factory.define('role_has_permission', 'role_has_permissions', async () => {
|
||||||
const view = await factory.create('view');
|
const permission = await factory.create('permission');
|
||||||
const field = await factory.create('resource_field');
|
const role = await factory.create('role');
|
||||||
|
const resource = await factory.create('resource');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
view_id: view.id,
|
role_id: role.id,
|
||||||
index: faker.random.number(),
|
permission_id: permission.id,
|
||||||
field_id: field.id,
|
resource_id: resource.id,
|
||||||
value: '',
|
};
|
||||||
comparator: '',
|
});
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('view_column', 'view_has_columns', async () => {
|
factory.define('resource', 'resources', () => ({
|
||||||
const view = await factory.create('view');
|
name: faker.lorem.word(),
|
||||||
const field = await factory.create('resource_field');
|
}));
|
||||||
|
|
||||||
return {
|
factory.define('view', 'views', async () => {
|
||||||
field_id: field.id,
|
const resource = await factory.create('resource');
|
||||||
view_id: view.id,
|
return {
|
||||||
// index: 1,
|
name: faker.lorem.word(),
|
||||||
};
|
resource_id: resource.id,
|
||||||
});
|
predefined: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
factory.define('expense', 'expenses', async () => {
|
factory.define('resource_field', 'resource_fields', async () => {
|
||||||
const paymentAccount = await factory.create('account');
|
const resource = await factory.create('resource');
|
||||||
const expenseAccount = await factory.create('account');
|
const dataTypes = ['select', 'date', 'text'];
|
||||||
const user = await factory.create('user');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
payment_account_id: paymentAccount.id,
|
label_name: faker.lorem.words(),
|
||||||
expense_account_id: expenseAccount.id,
|
key: faker.lorem.slug(),
|
||||||
user_id: user.id,
|
data_type: dataTypes[Math.floor(Math.random() * dataTypes.length)],
|
||||||
amount: faker.random.number(),
|
help_text: faker.lorem.words(),
|
||||||
currency_code: 'USD',
|
default: faker.lorem.word(),
|
||||||
};
|
resource_id: resource.id,
|
||||||
});
|
active: true,
|
||||||
|
columnable: true,
|
||||||
|
predefined: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
factory.define('option', 'options', async () => {
|
factory.define('resource_custom_field_metadata', 'resource_custom_fields_metadata', async () => {
|
||||||
return {
|
const resource = await factory.create('resource');
|
||||||
key: faker.lorem.slug(),
|
|
||||||
value: faker.lorem.slug(),
|
|
||||||
group: faker.lorem.slug(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('currency', 'currencies', async () => {
|
return {
|
||||||
return {
|
resource_id: resource.id,
|
||||||
currency_name: faker.lorem.slug(),
|
resource_item_id: 1,
|
||||||
currency_code: 'USD',
|
key: faker.lorem.words(),
|
||||||
};
|
value: faker.lorem.words(),
|
||||||
});
|
};
|
||||||
|
});
|
||||||
|
|
||||||
factory.define('exchange_rate', 'exchange_rates', async () => {
|
factory.define('view_role', 'view_roles', async () => {
|
||||||
return {
|
const view = await factory.create('view');
|
||||||
date: '2020-02-02',
|
const field = await factory.create('resource_field');
|
||||||
currency_code: 'USD',
|
|
||||||
exchange_rate: faker.random.number(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
factory.define('budget', 'budgets', async () => {
|
return {
|
||||||
return {
|
view_id: view.id,
|
||||||
name: faker.lorem.slug(),
|
index: faker.random.number(),
|
||||||
fiscal_year: '2020',
|
field_id: field.id,
|
||||||
period: 'month',
|
value: '',
|
||||||
account_types: 'profit_loss',
|
comparator: '',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
factory.define('budget_entry', 'budget_entries', async () => {
|
factory.define('view_column', 'view_has_columns', async () => {
|
||||||
const budget = await factory.create('budget');
|
const view = await factory.create('view');
|
||||||
const account = await factory.create('account');
|
const field = await factory.create('resource_field');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account_id: account.id,
|
field_id: field.id,
|
||||||
budget_id: budget.id,
|
view_id: view.id,
|
||||||
amount: 1000,
|
// index: 1,
|
||||||
order: 1,
|
};
|
||||||
};
|
});
|
||||||
});
|
|
||||||
|
|
||||||
export default factory;
|
factory.define('expense', 'expenses', async () => {
|
||||||
|
const paymentAccount = await factory.create('account');
|
||||||
|
const expenseAccount = await factory.create('account');
|
||||||
|
const user = await factory.create('user');
|
||||||
|
|
||||||
|
return {
|
||||||
|
payment_account_id: paymentAccount.id,
|
||||||
|
expense_account_id: expenseAccount.id,
|
||||||
|
user_id: user.id,
|
||||||
|
amount: faker.random.number(),
|
||||||
|
currency_code: 'USD',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('option', 'options', async () => {
|
||||||
|
return {
|
||||||
|
key: faker.lorem.slug(),
|
||||||
|
value: faker.lorem.slug(),
|
||||||
|
group: faker.lorem.slug(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('currency', 'currencies', async () => {
|
||||||
|
return {
|
||||||
|
currency_name: faker.lorem.slug(),
|
||||||
|
currency_code: 'USD',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('exchange_rate', 'exchange_rates', async () => {
|
||||||
|
return {
|
||||||
|
date: '2020-02-02',
|
||||||
|
currency_code: 'USD',
|
||||||
|
exchange_rate: faker.random.number(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('budget', 'budgets', async () => {
|
||||||
|
return {
|
||||||
|
name: faker.lorem.slug(),
|
||||||
|
fiscal_year: '2020',
|
||||||
|
period: 'month',
|
||||||
|
account_types: 'profit_loss',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
factory.define('budget_entry', 'budget_entries', async () => {
|
||||||
|
const budget = await factory.create('budget');
|
||||||
|
const account = await factory.create('account');
|
||||||
|
|
||||||
|
return {
|
||||||
|
account_id: account.id,
|
||||||
|
budget_id: budget.id,
|
||||||
|
amount: 1000,
|
||||||
|
order: 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|||||||
16
server/src/database/factories/system.js
Normal file
16
server/src/database/factories/system.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import KnexFactory from '@/lib/KnexFactory';
|
||||||
|
import systemDb from '@/database/knex';
|
||||||
|
import faker from 'faker';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const factory = new KnexFactory(systemDb);
|
||||||
|
|
||||||
|
factory.define('password_reset', 'password_resets', async () => {
|
||||||
|
return {
|
||||||
|
email: faker.lorem.email,
|
||||||
|
token: faker.lorem.slug,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import { knexSnakeCaseMappers } from 'objection';
|
|||||||
import knexfile from '@/../config/systemKnexfile';
|
import knexfile from '@/../config/systemKnexfile';
|
||||||
|
|
||||||
const config = knexfile[process.env.NODE_ENV];
|
const config = knexfile[process.env.NODE_ENV];
|
||||||
|
|
||||||
const knex = Knex({
|
const knex = Knex({
|
||||||
...config,
|
...config,
|
||||||
...knexSnakeCaseMappers({ upperCase: true }),
|
...knexSnakeCaseMappers({ upperCase: true }),
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import config from '@/../config/config';
|
|||||||
|
|
||||||
const knexConfig = knexfile[process.env.NODE_ENV];
|
const knexConfig = knexfile[process.env.NODE_ENV];
|
||||||
|
|
||||||
console.log({
|
|
||||||
superUser: config.manager.superUser,
|
|
||||||
superPassword: config.manager.superPassword,
|
|
||||||
});
|
|
||||||
const dbManager = knexManager.databaseManagerFactory({
|
const dbManager = knexManager.databaseManagerFactory({
|
||||||
knex: knexConfig,
|
knex: knexConfig,
|
||||||
dbManager: {
|
dbManager: {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ exports.up = (knex) => knex.schema.createTable('roles', (table) => {
|
|||||||
table.string('description');
|
table.string('description');
|
||||||
table.boolean('predefined').default(false);
|
table.boolean('predefined').default(false);
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
}).raw('ALTER TABLE `ROLES` AUTO_INCREMENT = 1000');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTable('roles');
|
exports.down = (knex) => knex.schema.dropTable('roles');
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ exports.up = function (knex) {
|
|||||||
|
|
||||||
table.date('invite_accepted_at');
|
table.date('invite_accepted_at');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
}).raw('ALTER TABLE `USERS` AUTO_INCREMENT = 1000');;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function (knex) {
|
exports.down = function (knex) {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('oauth_tokens', (table) => {
|
|
||||||
table.increments();
|
|
||||||
table.string('access_token');
|
|
||||||
table.date('access_token_expires_on');
|
|
||||||
table.integer('client_id').unsigned();
|
|
||||||
table.string('refresh_token');
|
|
||||||
table.date('refresh_token_expires_on');
|
|
||||||
table.integer('user_id').unsigned();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('oauth_tokens');
|
|
||||||
};
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('oauth_clients', (table) => {
|
|
||||||
table.increments();
|
|
||||||
table.integer('client_id').unsigned();
|
|
||||||
table.string('client_secret');
|
|
||||||
table.string('redirect_uri');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('oauth_clients');
|
|
||||||
@@ -7,7 +7,7 @@ exports.up = function (knex) {
|
|||||||
table.string('type');
|
table.string('type');
|
||||||
table.string('key');
|
table.string('key');
|
||||||
table.string('value');
|
table.string('value');
|
||||||
});
|
}).raw('ALTER TABLE `SETTINGS` AUTO_INCREMENT = 2000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('settings');
|
exports.down = (knex) => knex.schema.dropTableIfExists('settings');
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ exports.up = function (knex) {
|
|||||||
table.increments();
|
table.increments();
|
||||||
table.string('name');
|
table.string('name');
|
||||||
table.string('type');
|
table.string('type');
|
||||||
|
table.string('sku');
|
||||||
table.decimal('cost_price').unsigned();
|
table.decimal('cost_price').unsigned();
|
||||||
table.decimal('sell_price').unsigned();
|
table.decimal('sell_price').unsigned();
|
||||||
table.string('currency_code', 3);
|
table.string('currency_code', 3);
|
||||||
@@ -15,7 +16,7 @@ exports.up = function (knex) {
|
|||||||
table.integer('category_id').unsigned();
|
table.integer('category_id').unsigned();
|
||||||
table.integer('user_id').unsigned();
|
table.integer('user_id').unsigned();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
}).raw('ALTER TABLE `ITEMS` AUTO_INCREMENT = 1000');;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('items');
|
exports.down = (knex) => knex.schema.dropTableIfExists('items');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema.createTable('accounts', (table) => {
|
return knex.schema.createTable('accounts', (table) => {
|
||||||
table.increments();
|
table.bigIncrements('id').comment('Auto-generated id');;
|
||||||
table.string('name');
|
table.string('name');
|
||||||
table.integer('account_type_id');
|
table.integer('account_type_id');
|
||||||
table.integer('parent_account_id');
|
table.integer('parent_account_id');
|
||||||
@@ -11,7 +11,7 @@ exports.up = function (knex) {
|
|||||||
table.integer('index').unsigned();
|
table.integer('index').unsigned();
|
||||||
table.boolean('predefined').defaultTo(false);
|
table.boolean('predefined').defaultTo(false);
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}).then(() => {
|
}).raw('ALTER TABLE `ACCOUNTS` AUTO_INCREMENT = 1000').then(() => {
|
||||||
return knex.seed.run({
|
return knex.seed.run({
|
||||||
specific: 'seed_accounts.js',
|
specific: 'seed_accounts.js',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function (knex) {
|
|
||||||
return knex.schema.createTable('items_metadata', (table) => {
|
|
||||||
table.increments();
|
|
||||||
table.string('key');
|
|
||||||
table.string('value');
|
|
||||||
table.integer('item_id').unsigned();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = (knex) => knex.schema.dropTableIfExists('items_metadata');
|
|
||||||
@@ -7,7 +7,7 @@ exports.up = (knex) => {
|
|||||||
table.string('root_type');
|
table.string('root_type');
|
||||||
table.boolean('balance_sheet');
|
table.boolean('balance_sheet');
|
||||||
table.boolean('income_sheet');
|
table.boolean('income_sheet');
|
||||||
}).then(() => {
|
}).raw('ALTER TABLE `ACCOUNT_TYPES` AUTO_INCREMENT = 1000').then(() => {
|
||||||
return knex.seed.run({
|
return knex.seed.run({
|
||||||
specific: 'seed_account_types.js',
|
specific: 'seed_account_types.js',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ exports.up = function (knex) {
|
|||||||
table.integer('index');
|
table.integer('index');
|
||||||
table.json('options');
|
table.json('options');
|
||||||
table.integer('resource_id').unsigned();
|
table.integer('resource_id').unsigned();
|
||||||
}).then(() => {
|
}).raw('ALTER TABLE `RESOURCE_FIELDS` AUTO_INCREMENT = 1000').then(() => {
|
||||||
return knex.seed.run({
|
return knex.seed.run({
|
||||||
specific: 'seed_resources_fields.js',
|
specific: 'seed_resources_fields.js',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ exports.up = function (knex) {
|
|||||||
table.integer('view_id').unsigned();
|
table.integer('view_id').unsigned();
|
||||||
table.integer('field_id').unsigned();
|
table.integer('field_id').unsigned();
|
||||||
table.integer('index').unsigned();
|
table.integer('index').unsigned();
|
||||||
|
}).raw('ALTER TABLE `ITEMS_CATEGORIES` AUTO_INCREMENT = 1000').then(() => {
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ exports.up = function (knex) {
|
|||||||
table.string('comparator');
|
table.string('comparator');
|
||||||
table.string('value');
|
table.string('value');
|
||||||
table.integer('view_id').unsigned();
|
table.integer('view_id').unsigned();
|
||||||
}).then(() => {
|
}).raw('ALTER TABLE `VIEW_ROLES` AUTO_INCREMENT = 1000').then(() => {
|
||||||
return knex.seed.run({
|
return knex.seed.run({
|
||||||
specific: 'seed_views_roles.js',
|
specific: 'seed_views_roles.js',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ exports.up = function (knex) {
|
|||||||
table.integer('resource_id').unsigned().references('id').inTable('resources');
|
table.integer('resource_id').unsigned().references('id').inTable('resources');
|
||||||
table.boolean('favourite');
|
table.boolean('favourite');
|
||||||
table.string('roles_logic_expression');
|
table.string('roles_logic_expression');
|
||||||
}).then(() => {
|
}).raw('ALTER TABLE `VIEWS` AUTO_INCREMENT = 1000').then(() => {
|
||||||
return knex.seed.run({
|
return knex.seed.run({
|
||||||
specific: 'seed_views.js',
|
specific: 'seed_views.js',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ exports.up = function(knex) {
|
|||||||
table.integer('user_id').unsigned();
|
table.integer('user_id').unsigned();
|
||||||
table.date('date');
|
table.date('date');
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
}).raw('ALTER TABLE `ACCOUNTS_TRANSACTIONS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function(knex) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ exports.up = function(knex) {
|
|||||||
table.string('attachment_file');
|
table.string('attachment_file');
|
||||||
table.integer('user_id').unsigned();
|
table.integer('user_id').unsigned();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
});
|
}).raw('ALTER TABLE `MANUAL_JOURNALS` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function(knex) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ exports.up = function(knex) {
|
|||||||
table.increments();
|
table.increments();
|
||||||
table.string('currency_name');
|
table.string('currency_name');
|
||||||
table.string('currency_code', 4);
|
table.string('currency_code', 4);
|
||||||
})
|
}).raw('ALTER TABLE `CURRENCIES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function(knex) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ exports.up = function(knex) {
|
|||||||
table.string('currency_code', 4);
|
table.string('currency_code', 4);
|
||||||
table.decimal('exchange_rate');
|
table.decimal('exchange_rate');
|
||||||
table.date('date');
|
table.date('date');
|
||||||
});
|
}).raw('ALTER TABLE `EXCHANGE_RATES` AUTO_INCREMENT = 1000');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function(knex) {
|
exports.down = function(knex) {
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ export default {
|
|||||||
this.transferToAnotherAccount.validation,
|
this.transferToAnotherAccount.validation,
|
||||||
asyncMiddleware(this.transferToAnotherAccount.handler));
|
asyncMiddleware(this.transferToAnotherAccount.handler));
|
||||||
|
|
||||||
|
router.post('/bulk/:type(activate|inactivate)',
|
||||||
|
this.bulkInactivateAccounts.validation,
|
||||||
|
asyncMiddleware(this.bulkInactivateAccounts.handler));
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -541,4 +545,47 @@ export default {
|
|||||||
return res.status(200).send();
|
return res.status(200).send();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk acvtivate/inactivate the given accounts.
|
||||||
|
*/
|
||||||
|
bulkInactivateAccounts: {
|
||||||
|
validation: [
|
||||||
|
query('ids').isArray({ min: 2 }),
|
||||||
|
query('ids.*').isNumeric().toInt(),
|
||||||
|
param('type').exists().isIn(['activate', 'inactivate']),
|
||||||
|
],
|
||||||
|
async handler(req, res) {
|
||||||
|
const validationErrors = validationResult(req);
|
||||||
|
|
||||||
|
if (!validationErrors.isEmpty()) {
|
||||||
|
return res.boom.badData(null, {
|
||||||
|
code: 'validation_error', ...validationErrors,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const filter = {
|
||||||
|
ids: [],
|
||||||
|
...req.query,
|
||||||
|
};
|
||||||
|
const { Account } = req.models;
|
||||||
|
const { type } = req.params;
|
||||||
|
|
||||||
|
const storedAccounts = await Account.query().whereIn('id', filter.ids);
|
||||||
|
const storedAccountsIds = storedAccounts.map((account) => account.id);
|
||||||
|
const notFoundAccounts = difference(filter.ids, storedAccountsIds);
|
||||||
|
|
||||||
|
if (notFoundAccounts.length > 0) {
|
||||||
|
return res.status(400).send({
|
||||||
|
errors: [{ type: 'ACCOUNTS.NOT.FOUND', code: 200 }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const updatedAccounts = await Account.query()
|
||||||
|
.whereIn('id', storedAccountsIds)
|
||||||
|
.patch({
|
||||||
|
active: type === 'activate' ? 1 : 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).send({ ids: storedAccountsIds });
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Mustache from 'mustache';
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import uniqid from 'uniqid';
|
import uniqid from 'uniqid';
|
||||||
|
import moment from 'moment';
|
||||||
import Logger from '@/services/Logger';
|
import Logger from '@/services/Logger';
|
||||||
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
||||||
import SystemUser from '@/system/models/SystemUser';
|
import SystemUser from '@/system/models/SystemUser';
|
||||||
@@ -19,6 +20,7 @@ import TenantsManager from '@/system/TenantsManager';
|
|||||||
import TenantModel from '@/models/TenantModel';
|
import TenantModel from '@/models/TenantModel';
|
||||||
import PasswordReset from '@/system/models/PasswordReset';
|
import PasswordReset from '@/system/models/PasswordReset';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Constructor method.
|
* Constructor method.
|
||||||
@@ -51,7 +53,7 @@ export default {
|
|||||||
login: {
|
login: {
|
||||||
validation: [
|
validation: [
|
||||||
check('crediential').exists().isEmail(),
|
check('crediential').exists().isEmail(),
|
||||||
check('password').exists().isLength({ min: 4 }),
|
check('password').exists().isLength({ min: 5 }),
|
||||||
],
|
],
|
||||||
async handler(req, res) {
|
async handler(req, res) {
|
||||||
const validationErrors = validationResult(req);
|
const validationErrors = validationResult(req);
|
||||||
@@ -87,7 +89,17 @@ export default {
|
|||||||
errors: [{ type: 'USER_INACTIVE', code: 110 }],
|
errors: [{ type: 'USER_INACTIVE', code: 110 }],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// user.update({ last_login_at: new Date() });
|
const lastLoginAt = moment().format('YYYY/MM/DD HH:mm:ss');
|
||||||
|
|
||||||
|
const updateTenantUser = TenantUser.tenant().query()
|
||||||
|
.where('id', user.id)
|
||||||
|
.update({ last_login_at: lastLoginAt });
|
||||||
|
|
||||||
|
const updateSystemUser = SystemUser.query()
|
||||||
|
.where('id', user.id)
|
||||||
|
.update({ last_login_at: lastLoginAt });
|
||||||
|
|
||||||
|
await Promise.all([updateTenantUser, updateSystemUser]);
|
||||||
|
|
||||||
const token = jwt.sign(
|
const token = jwt.sign(
|
||||||
{ email: user.email, _id: user.id },
|
{ email: user.email, _id: user.id },
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
validationResult,
|
validationResult,
|
||||||
} from 'express-validator';
|
} from 'express-validator';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { difference } from 'lodash';
|
||||||
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -27,6 +28,10 @@ export default {
|
|||||||
this.editExchangeRate.validation,
|
this.editExchangeRate.validation,
|
||||||
asyncMiddleware(this.editExchangeRate.handler));
|
asyncMiddleware(this.editExchangeRate.handler));
|
||||||
|
|
||||||
|
router.delete('/bulk',
|
||||||
|
this.bulkDeleteExchangeRates.validation,
|
||||||
|
asyncMiddleware(this.bulkDeleteExchangeRates.handler));
|
||||||
|
|
||||||
router.delete('/:id',
|
router.delete('/:id',
|
||||||
this.deleteExchangeRate.validation,
|
this.deleteExchangeRate.validation,
|
||||||
asyncMiddleware(this.deleteExchangeRate.handler));
|
asyncMiddleware(this.deleteExchangeRate.handler));
|
||||||
@@ -166,4 +171,39 @@ export default {
|
|||||||
return res.status(200).send({ id });
|
return res.status(200).send({ id });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
bulkDeleteExchangeRates: {
|
||||||
|
validation: [
|
||||||
|
query('ids').isArray({ min: 2 }),
|
||||||
|
query('ids.*').isNumeric().toInt(),
|
||||||
|
],
|
||||||
|
async handler(req, res) {
|
||||||
|
const validationErrors = validationResult(req);
|
||||||
|
|
||||||
|
if (!validationErrors.isEmpty()) {
|
||||||
|
return res.boom.badData(null, {
|
||||||
|
code: 'validation_error', ...validationErrors,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
ids: [],
|
||||||
|
...req.query,
|
||||||
|
};
|
||||||
|
const { ExchangeRate } = req.models;
|
||||||
|
|
||||||
|
const exchangeRates = await ExchangeRate.query().whereIn('id', filter.ids);
|
||||||
|
const exchangeRatesIds = exchangeRates.map((category) => category.id);
|
||||||
|
const notFoundExRates = difference(filter.ids, exchangeRatesIds);
|
||||||
|
|
||||||
|
if (notFoundExRates.length > 0) {
|
||||||
|
return res.status(400).send({
|
||||||
|
errors: [{ type: 'EXCHANGE.RATES.IS.NOT.FOUND', code: 200, ids: notFoundExRates }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await ExchangeRate.query().whereIn('id', exchangeRatesIds).delete();
|
||||||
|
|
||||||
|
return res.status(200).send({ ids: exchangeRatesIds });
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
validationResult,
|
validationResult,
|
||||||
query,
|
query,
|
||||||
} from 'express-validator';
|
} from 'express-validator';
|
||||||
|
import { difference } from 'lodash';
|
||||||
import asyncMiddleware from '../middleware/asyncMiddleware';
|
import asyncMiddleware from '../middleware/asyncMiddleware';
|
||||||
import {
|
import {
|
||||||
DynamicFilter,
|
DynamicFilter,
|
||||||
@@ -15,6 +16,7 @@ import {
|
|||||||
mapFilterRolesToDynamicFilter,
|
mapFilterRolesToDynamicFilter,
|
||||||
} from '@/lib/ViewRolesBuilder';
|
} from '@/lib/ViewRolesBuilder';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Router constructor method.
|
* Router constructor method.
|
||||||
@@ -31,6 +33,10 @@ export default {
|
|||||||
this.newCategory.validation,
|
this.newCategory.validation,
|
||||||
asyncMiddleware(this.newCategory.handler));
|
asyncMiddleware(this.newCategory.handler));
|
||||||
|
|
||||||
|
router.delete('/bulk',
|
||||||
|
this.bulkDeleteCategories.validation,
|
||||||
|
asyncMiddleware(this.bulkDeleteCategories.handler));
|
||||||
|
|
||||||
router.delete('/:id',
|
router.delete('/:id',
|
||||||
this.deleteItem.validation,
|
this.deleteItem.validation,
|
||||||
asyncMiddleware(this.deleteItem.handler));
|
asyncMiddleware(this.deleteItem.handler));
|
||||||
@@ -43,6 +49,8 @@ export default {
|
|||||||
this.getList.validation,
|
this.getList.validation,
|
||||||
asyncMiddleware(this.getList.handler));
|
asyncMiddleware(this.getList.handler));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -145,7 +153,7 @@ export default {
|
|||||||
.where('id', id)
|
.where('id', id)
|
||||||
.update({ ...form });
|
.update({ ...form });
|
||||||
|
|
||||||
return res.status(200).send({ id: updateItemCategory });
|
return res.status(200).send({ id });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -274,8 +282,46 @@ export default {
|
|||||||
errors: [{ type: 'CATEGORY_NOT_FOUND', code: 100 }],
|
errors: [{ type: 'CATEGORY_NOT_FOUND', code: 100 }],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send({ category: item.toJSON() });
|
return res.status(200).send({ category: item.toJSON() });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk delete the given item categories.
|
||||||
|
*/
|
||||||
|
bulkDeleteCategories: {
|
||||||
|
validation: [
|
||||||
|
query('ids').isArray({ min: 2 }),
|
||||||
|
query('ids.*').isNumeric().toInt(),
|
||||||
|
],
|
||||||
|
async handler(req, res) {
|
||||||
|
const validationErrors = validationResult(req);
|
||||||
|
|
||||||
|
if (!validationErrors.isEmpty()) {
|
||||||
|
return res.boom.badData(null, {
|
||||||
|
code: 'validation_error', ...validationErrors,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const filter = {
|
||||||
|
ids: [],
|
||||||
|
...req.query,
|
||||||
|
};
|
||||||
|
const { ItemCategory } = req.models;
|
||||||
|
|
||||||
|
const itemCategories = await ItemCategory.query().whereIn('id', filter.ids);
|
||||||
|
const itemCategoriesIds = itemCategories.map((category) => category.id);
|
||||||
|
const notFoundCategories = difference(filter.ids, itemCategoriesIds);
|
||||||
|
|
||||||
|
if (notFoundCategories.length > 0) {
|
||||||
|
return res.status(400).send({
|
||||||
|
errors: [{ type: 'ITEM.CATEGORIES.IDS.NOT.FOUND', code: 200 }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await ItemCategory.query().whereIn('id', filter.ids).delete();
|
||||||
|
|
||||||
|
return res.status(200).send({ ids: filter.ids });
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import Logger from '@/services/Logger';
|
|||||||
|
|
||||||
const fsPromises = fs.promises;
|
const fsPromises = fs.promises;
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Router constructor.
|
* Router constructor.
|
||||||
@@ -80,6 +81,7 @@ export default {
|
|||||||
code: 'validation_error', ...validationErrors,
|
code: 'validation_error', ...validationErrors,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const { user } = req;
|
||||||
const form = {
|
const form = {
|
||||||
custom_fields: [],
|
custom_fields: [],
|
||||||
media_ids: [],
|
media_ids: [],
|
||||||
@@ -129,8 +131,10 @@ export default {
|
|||||||
itemCategory,
|
itemCategory,
|
||||||
inventoryAccount,
|
inventoryAccount,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
costAccountPromise, sellAccountPromise,
|
costAccountPromise,
|
||||||
itemCategoryPromise, inventoryAccountPromise,
|
sellAccountPromise,
|
||||||
|
itemCategoryPromise,
|
||||||
|
inventoryAccountPromise,
|
||||||
]);
|
]);
|
||||||
if (!costAccount) {
|
if (!costAccount) {
|
||||||
errorReasons.push({ type: 'COST_ACCOUNT_NOT_FOUND', code: 100 });
|
errorReasons.push({ type: 'COST_ACCOUNT_NOT_FOUND', code: 100 });
|
||||||
@@ -152,11 +156,14 @@ export default {
|
|||||||
const item = await Item.query().insertAndFetch({
|
const item = await Item.query().insertAndFetch({
|
||||||
name: form.name,
|
name: form.name,
|
||||||
type: form.type,
|
type: form.type,
|
||||||
|
sku: form.sku,
|
||||||
cost_price: form.cost_price,
|
cost_price: form.cost_price,
|
||||||
sell_price: form.sell_price,
|
sell_price: form.sell_price,
|
||||||
sell_account_id: form.sell_account_id,
|
sell_account_id: form.sell_account_id,
|
||||||
cost_account_id: form.cost_account_id,
|
cost_account_id: form.cost_account_id,
|
||||||
currency_code: form.currency_code,
|
currency_code: form.currency_code,
|
||||||
|
category_id: form.category_id,
|
||||||
|
user_id: user.id,
|
||||||
note: form.note,
|
note: form.note,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -239,7 +246,7 @@ export default {
|
|||||||
errorReasons.push({ type: 'ITEM_CATEGORY_NOT_FOUND', code: 140 });
|
errorReasons.push({ type: 'ITEM_CATEGORY_NOT_FOUND', code: 140 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { attachment } = req.files;
|
const attachment = req.files && req.files.attachment ? req.files.attachment : null;
|
||||||
const attachmentsMimes = ['image/png', 'image/jpeg'];
|
const attachmentsMimes = ['image/png', 'image/jpeg'];
|
||||||
|
|
||||||
// Validate the attachment.
|
// Validate the attachment.
|
||||||
@@ -277,7 +284,6 @@ export default {
|
|||||||
cost_account_id: form.cost_account_id,
|
cost_account_id: form.cost_account_id,
|
||||||
category_id: form.category_id,
|
category_id: form.category_id,
|
||||||
note: form.note,
|
note: form.note,
|
||||||
attachment_file: (attachment) ? item.attachmentFile : null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save links of new inserted media that associated to the item model.
|
// Save links of new inserted media that associated to the item model.
|
||||||
|
|||||||
55
server/src/lib/KnexFactory/index.js
Normal file
55
server/src/lib/KnexFactory/index.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
const { extend, isFunction, isObject } = require('lodash');
|
||||||
|
|
||||||
|
export default class KnexFactory {
|
||||||
|
|
||||||
|
constructor(knex) {
|
||||||
|
this.knex = knex;
|
||||||
|
|
||||||
|
this.factories = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
define(name, tableName, defaultAttributes) {
|
||||||
|
this.factories[name] = { tableName, defaultAttributes };
|
||||||
|
}
|
||||||
|
|
||||||
|
async build(factoryName, attributes) {
|
||||||
|
const factory = this.factories[factoryName];
|
||||||
|
|
||||||
|
if (!factory) {
|
||||||
|
throw `Unkown factory: ${factoryName}`;
|
||||||
|
}
|
||||||
|
let { defaultAttributes } = factory;
|
||||||
|
const insertData = {};
|
||||||
|
|
||||||
|
if( 'function' === typeof defaultAttributes) {
|
||||||
|
defaultAttributes = await defaultAttributes();
|
||||||
|
}
|
||||||
|
extend(insertData, defaultAttributes, attributes);
|
||||||
|
|
||||||
|
for (let k in insertData) {
|
||||||
|
const v = insertData[k];
|
||||||
|
|
||||||
|
if (isFunction(v)) {
|
||||||
|
insertData[k] = await v();
|
||||||
|
} else {
|
||||||
|
insertData[k] = await v;
|
||||||
|
}
|
||||||
|
if (isObject(insertData[k]) && insertData[k].id) {
|
||||||
|
insertData[k] = insertData[k].id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return insertData;
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(factoryName, attributes) {
|
||||||
|
const factory = this.factories[factoryName];
|
||||||
|
const insertData = await this.build(factoryName, attributes);
|
||||||
|
const { tableName } = factory;
|
||||||
|
|
||||||
|
const [id] = await this.knex(tableName).insert(insertData);
|
||||||
|
const record = await this.knex(tableName).where({ id }).first();
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,13 +18,16 @@ export default class Option extends mixin(TenantModel, [mixin]) {
|
|||||||
static query(...args) {
|
static query(...args) {
|
||||||
return super.query(...args).runAfter((result) => {
|
return super.query(...args).runAfter((result) => {
|
||||||
if (result instanceof MetableCollection) {
|
if (result instanceof MetableCollection) {
|
||||||
result.setModel(Option);
|
result.setModel(this.tenant());
|
||||||
result.setExtraColumns(['group']);
|
result.setExtraColumns(['group']);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model collection.
|
||||||
|
*/
|
||||||
static get collection() {
|
static get collection() {
|
||||||
return MetableCollection;
|
return MetableCollection;
|
||||||
}
|
}
|
||||||
|
|||||||
12
server/src/system/TenantEnvironment.js
Normal file
12
server/src/system/TenantEnvironment.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default class TenantEnviroment {
|
||||||
|
|
||||||
|
static get currentTenant() {
|
||||||
|
return this.currentTenantWebsite;
|
||||||
|
}
|
||||||
|
|
||||||
|
static set currentTenant(website) {
|
||||||
|
this.currentTenantWebsite = website;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,20 @@ import Knex from 'knex';
|
|||||||
import { knexSnakeCaseMappers } from 'objection';
|
import { knexSnakeCaseMappers } from 'objection';
|
||||||
import Tenant from '@/system/models/Tenant';
|
import Tenant from '@/system/models/Tenant';
|
||||||
import config from '@/../config/config';
|
import config from '@/../config/config';
|
||||||
|
import TenantModel from '@/models/TenantModel';
|
||||||
|
import uniqid from 'uniqid';
|
||||||
|
import dbManager from '@/database/manager';
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
|
import SystemUser from '@/system/models/SystemUser';
|
||||||
|
import TenantUser from '@/models/TenantUser';
|
||||||
|
// import TenantModel from '@/models/TenantModel';
|
||||||
|
|
||||||
|
// const TenantWebsite: {
|
||||||
|
// tenantDb: Knex,
|
||||||
|
// tenantId: Number,
|
||||||
|
// tenantOrganizationId: String,
|
||||||
|
// }
|
||||||
|
|
||||||
export default class TenantsManager {
|
export default class TenantsManager {
|
||||||
|
|
||||||
@@ -16,6 +30,65 @@ export default class TenantsManager {
|
|||||||
return tenant;
|
return tenant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new tenant database.
|
||||||
|
* @param {Integer} uniqId
|
||||||
|
* @return {TenantWebsite}
|
||||||
|
*/
|
||||||
|
static async createTenant(uniqId) {
|
||||||
|
const organizationId = uniqId || uniqid();
|
||||||
|
const tenantOrganization = await Tenant.query().insert({
|
||||||
|
organization_id: organizationId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tenantDbName = `bigcapital_tenant_${organizationId}`;
|
||||||
|
await dbManager.createDb(tenantDbName);
|
||||||
|
|
||||||
|
const tenantDb = TenantsManager.knexInstance(organizationId);
|
||||||
|
await tenantDb.migrate.latest();
|
||||||
|
|
||||||
|
return {
|
||||||
|
tenantDb,
|
||||||
|
tenantId: tenantOrganization.id,
|
||||||
|
organizationId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop tenant database of the given tenant website.
|
||||||
|
* @param {TenantWebsite} tenantWebsite
|
||||||
|
*/
|
||||||
|
static async dropTenant(tenantWebsite) {
|
||||||
|
const tenantDbName = `bigcapital_tenant_${tenantWebsite.organizationId}`;
|
||||||
|
await dbManager.dropDb(tenantDbName);
|
||||||
|
|
||||||
|
await SystemUser.query()
|
||||||
|
.where('tenant_id', tenantWebsite.tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a user that associate to the given tenant.
|
||||||
|
*/
|
||||||
|
static async createTenantUser(tenantWebsite, user) {
|
||||||
|
const userInsert = { ...user };
|
||||||
|
|
||||||
|
const systemUser = await SystemUser.query().insert({
|
||||||
|
...user,
|
||||||
|
tenant_id: tenantWebsite.tenantId,
|
||||||
|
});
|
||||||
|
TenantModel.knexBinded = tenantWebsite.tenantDb;
|
||||||
|
|
||||||
|
const tenantUser = await TenantUser.bindKnex(tenantWebsite.tenantDb)
|
||||||
|
.query()
|
||||||
|
.insert({
|
||||||
|
...omit(userInsert, ['password']),
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...tenantUser,
|
||||||
|
...systemUser
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all tenants metadata from system storage.
|
* Retrieve all tenants metadata from system storage.
|
||||||
*/
|
*/
|
||||||
@@ -43,6 +116,7 @@ export default class TenantsManager {
|
|||||||
seeds: {
|
seeds: {
|
||||||
directory: config.tenant.seeds_dir,
|
directory: config.tenant.seeds_dir,
|
||||||
},
|
},
|
||||||
|
pool: { min: 0, max: 5 },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
server/tests/dbInit.js
Normal file
37
server/tests/dbInit.js
Normal 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,
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
on: '2'
|
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql/mysql-server:5.7
|
image: mysql/mysql-server:5.7
|
||||||
@@ -9,3 +9,6 @@ services:
|
|||||||
- MYSQL_DATABASE=moosher_test
|
- MYSQL_DATABASE=moosher_test
|
||||||
- MYSQL_USER=moosher
|
- MYSQL_USER=moosher
|
||||||
- MYSQL_PASSWORD=moosher
|
- MYSQL_PASSWORD=moosher
|
||||||
|
tmpfs:
|
||||||
|
- /var/lib/mysql/:rw,noexec,nosuid,size=600m
|
||||||
|
- /tmp/:rw,noexec,nosuid,size=50m
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
import { create, expect } from '~/testInit';
|
import {
|
||||||
|
expect,
|
||||||
|
} from '~/testInit';
|
||||||
import Account from '@/models/Account';
|
import Account from '@/models/Account';
|
||||||
import AccountType from '@/models/AccountType';
|
import AccountType from '@/models/AccountType';
|
||||||
|
import {
|
||||||
|
tenantFactory,
|
||||||
|
tenantWebsite
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: Account', () => {
|
describe('Model: Account', () => {
|
||||||
it('Should account model belongs to the associated account type model.', async () => {
|
it('Should account model belongs to the associated account type model.', async () => {
|
||||||
const accountType = await create('account_type');
|
const accountType = await tenantFactory.create('account_type');
|
||||||
const account = await create('account', { account_type_id: accountType.id });
|
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)
|
.where('id', account.id)
|
||||||
.withGraphFetched('type')
|
.withGraphFetched('type')
|
||||||
.first();
|
.first();
|
||||||
@@ -16,9 +23,9 @@ describe('Model: Account', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should account model has one balance model that associated to the account model.', async () => {
|
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)
|
.where('id', accountBalance.accountId)
|
||||||
.withGraphFetched('balance')
|
.withGraphFetched('balance')
|
||||||
.first();
|
.first();
|
||||||
@@ -27,10 +34,10 @@ describe('Model: Account', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should account model has many transactions models that associated to the account model.', async () => {
|
it('Should account model has many transactions models that associated to the account model.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const accountTransaction = await create('account_transaction', { account_id: account.id });
|
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');
|
const transactionsModels = await accountModel.$relatedQuery('transactions');
|
||||||
|
|
||||||
expect(transactionsModels.length).equals(1);
|
expect(transactionsModels.length).equals(1);
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
import { create, expect } from '~/testInit';
|
import { create, expect } from '~/testInit';
|
||||||
import '@/models/Account';
|
import '@/models/Account';
|
||||||
import AccountType from '@/models/AccountType';
|
import AccountType from '@/models/AccountType';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: AccountType', () => {
|
describe('Model: AccountType', () => {
|
||||||
it('Shoud account type model has many associated accounts.', async () => {
|
it('Shoud account type model has many associated accounts.', async () => {
|
||||||
const accountType = await create('account_type');
|
const accountType = await tenantFactory.create('account_type');
|
||||||
await create('account', { account_type_id: accountType.id });
|
await tenantFactory.create('account', { account_type_id: accountType.id });
|
||||||
await 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');
|
const typeAccounts = await accountTypeModel.$relatedQuery('accounts');
|
||||||
|
|
||||||
expect(typeAccounts.length).equals(2);
|
expect(typeAccounts.length).equals(2);
|
||||||
|
|||||||
@@ -2,27 +2,21 @@ import { create, expect } from '~/testInit';
|
|||||||
import Item from '@/models/Item';
|
import Item from '@/models/Item';
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
import itemCategory from '@/models/ItemCategory';
|
import itemCategory from '@/models/ItemCategory';
|
||||||
import '@/models/ItemMetadata';
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: Item', () => {
|
describe('Model: Item', () => {
|
||||||
it('Should item model belongs to the associated category model.', async () => {
|
it('Should item model belongs to the associated category model.', async () => {
|
||||||
const category = await create('item_category');
|
const category = await tenantFactory.create('item_category');
|
||||||
const item = await create('item', { category_id: category.id });
|
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');
|
const itemCategoryModel = await itemModel.$relatedQuery('category');
|
||||||
|
|
||||||
expect(itemCategoryModel.attributes.id).equals(category.id);
|
expect(itemCategoryModel.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);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
import { create, expect } from '~/testInit';
|
import { create, expect } from '~/testInit';
|
||||||
import '@/models/Item';
|
import '@/models/Item';
|
||||||
import ItemCategory from '@/models/ItemCategory';
|
import ItemCategory from '@/models/ItemCategory';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: ItemCategories', () => {
|
describe('Model: ItemCategories', () => {
|
||||||
it('Shoud item category model has many associated items.', async () => {
|
it('Shoud item category model has many associated items.', async () => {
|
||||||
const category = await create('item_category');
|
const category = await tenantFactory.create('item_category');
|
||||||
await create('item', { category_id: category.id });
|
await tenantFactory.create('item', { category_id: category.id });
|
||||||
await create('item', { category_id: category.id });
|
await tenantFactory.create('item', { category_id: category.id });
|
||||||
|
|
||||||
const categoryModel = await ItemCategory.where('id', category.id).fetch();
|
const categoryModel = await ItemCategory.tenant().query()
|
||||||
const categoryItems = await categoryModel.items().fetch();
|
.where('id', category.id).first();
|
||||||
|
|
||||||
|
const categoryItems = await categoryModel.$relatedQuery('items');
|
||||||
|
|
||||||
expect(categoryItems.length).equals(2);
|
expect(categoryItems.length).equals(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
import { create, expect } from '~/testInit';
|
import { create, expect } from '~/testInit';
|
||||||
import Option from '@/models/Option';
|
import Option from '@/models/Option';
|
||||||
import MetableCollection from '@/lib/Metable/MetableCollection';
|
import MetableCollection from '@/lib/Metable/MetableCollection';
|
||||||
|
import {
|
||||||
|
tenantFactory,
|
||||||
|
tenantWebsite,
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: Option', () => {
|
describe('Model: Option', () => {
|
||||||
it('Should result collection be instance of `MetableCollection` class.', async () => {
|
it('Should result collection be instance of `MetableCollection` class.', async () => {
|
||||||
await create('option');
|
await tenantFactory.create('option');
|
||||||
await create('option');
|
await tenantFactory.create('option');
|
||||||
const options = await Option.query();
|
const options = await Option.tenant().query();
|
||||||
|
|
||||||
expect(options).to.be.an.instanceof(MetableCollection);
|
expect(options).to.be.an.instanceof(MetableCollection);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,22 +2,28 @@ import { create, expect } from '~/testInit';
|
|||||||
import Resource from '@/models/Resource';
|
import Resource from '@/models/Resource';
|
||||||
import '@/models/View';
|
import '@/models/View';
|
||||||
import '@/models/ResourceField';
|
import '@/models/ResourceField';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: Resource', () => {
|
describe('Model: Resource', () => {
|
||||||
it('Resource model may has many associated views.', async () => {
|
it('Resource model may has many associated views.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
await create('view', { resource_id: view.resourceId });
|
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');
|
const resourceViews = await resourceModel.$relatedQuery('views');
|
||||||
|
|
||||||
expect(resourceViews).to.have.lengthOf(2);
|
expect(resourceViews).to.have.lengthOf(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Resource model may has many fields.', async () => {
|
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');
|
const resourceFields = await resourceModel.$relatedQuery('fields');
|
||||||
|
|
||||||
expect(resourceFields).to.have.lengthOf(1);
|
expect(resourceFields).to.have.lengthOf(1);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,46 +1,23 @@
|
|||||||
import { create, expect } from '~/testInit';
|
import { create, expect } from '~/testInit';
|
||||||
import User from '@/models/User';
|
import User from '@/models/TenantUser';
|
||||||
import '@/models/Role';
|
import '@/models/Role';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: User', () => {
|
describe('Model: User', () => {
|
||||||
describe('relations', () => {
|
describe('relations', () => {
|
||||||
it('User model may has many associated roles.', async () => {
|
it('User model may has many associated roles.', async () => {
|
||||||
const userHasRole = await create('user_has_role');
|
const userHasRole = await tenantFactory.create('user_has_role');
|
||||||
await create('user_has_role', { user_id: userHasRole.user_id });
|
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');
|
const userRoles = await userModel.$relatedQuery('roles');
|
||||||
|
|
||||||
expect(userRoles).to.have.lengthOf(1);
|
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,37 +3,43 @@ import View from '@/models/View';
|
|||||||
import Resource from '@/models/Resource';
|
import Resource from '@/models/Resource';
|
||||||
import ResourceField from '@/models/ResourceField';
|
import ResourceField from '@/models/ResourceField';
|
||||||
import ViewRole from '@/models/ViewRole';
|
import ViewRole from '@/models/ViewRole';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
|
|
||||||
describe('Model: View', () => {
|
describe('Model: View', () => {
|
||||||
it('View model may has many associated resource.', async () => {
|
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 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.id).equals(foundResource.id);
|
||||||
expect(viewResource.name).equals(foundResource.name);
|
expect(viewResource.name).equals(foundResource.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('View model may has many associated view roles.', async () => {
|
it('View model may has many associated view roles.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
await create('view_role', { view_id: view.id });
|
await tenantFactory.create('view_role', { view_id: view.id });
|
||||||
await 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 viewModel = await View.tenant().query().findById(view.id);
|
||||||
const viewRoles = await viewModel.$relatedQuery('viewRoles');
|
const viewRoles = await viewModel.$relatedQuery('roles');
|
||||||
|
|
||||||
expect(viewRoles).to.have.lengthOf(2);
|
expect(viewRoles).to.have.lengthOf(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('View model may has many associated view columns', async () => {
|
it('View model may has many associated view columns', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
await create('view_column', { view_id: view.id });
|
await tenantFactory.create('view_column', { view_id: view.id });
|
||||||
await 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');
|
const viewColumns = await viewModel.$relatedQuery('columns');
|
||||||
|
|
||||||
expect(viewColumns).to.have.lengthOf(2);
|
expect(viewColumns).to.have.lengthOf(2);
|
||||||
|
|||||||
31
server/tests/mysql-tmpfs.sh
Normal file
31
server/tests/mysql-tmpfs.sh
Normal 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}"
|
||||||
@@ -1,30 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
expect,
|
expect,
|
||||||
create,
|
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import ManualJournal from '@/models/ManualJournal';
|
import ManualJournal from '@/models/ManualJournal';
|
||||||
import AccountTransaction from '@/models/AccountTransaction';
|
import AccountTransaction from '@/models/AccountTransaction';
|
||||||
import AccountBalance from '@/models/AccountBalance';
|
import AccountBalance from '@/models/AccountBalance';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: `/accounting`', () => {
|
describe('routes: `/accounting`', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('route: `/accounting/make-journal-entries`', async () => {
|
describe('route: `/accounting/make-journal-entries`', async () => {
|
||||||
it('Should sumation of credit or debit does not equal zero.', 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()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
@@ -50,10 +46,11 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should all credit entries equal debit.', async () => {
|
it('Should all credit entries equal debit.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
@@ -79,12 +76,13 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should journal reference be not exists.', async () => {
|
it('Should journal reference be not exists.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: manualJournal.journalNumber,
|
journal_number: manualJournal.journalNumber,
|
||||||
@@ -113,6 +111,7 @@ describe('routes: `/accounting`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
@@ -138,12 +137,13 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should discard journal entries that has null credit and debit amount.', async () => {
|
it('Should discard journal entries that has null credit and debit amount.', async () => {
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '1000',
|
journal_number: '1000',
|
||||||
@@ -169,12 +169,13 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should store manual journal transaction to the storage.', async () => {
|
it('Should store manual journal transaction to the storage.', async () => {
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date('2020-2-2').toISOString(),
|
date: new Date('2020-2-2').toISOString(),
|
||||||
journal_number: '1000',
|
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);
|
expect(foundManualJournal.length).equals(1);
|
||||||
|
|
||||||
@@ -202,17 +203,19 @@ describe('routes: `/accounting`', () => {
|
|||||||
expect(foundManualJournal[0].amount).equals(1000);
|
expect(foundManualJournal[0].amount).equals(1000);
|
||||||
expect(moment(foundManualJournal[0].date).format('YYYY-MM-DD')).equals('2020-02-02');
|
expect(moment(foundManualJournal[0].date).format('YYYY-MM-DD')).equals('2020-02-02');
|
||||||
expect(foundManualJournal[0].description).equals('Description here.');
|
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 () => {
|
it('Should store journal transactions to the storage.', async () => {
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounting/make-journal-entries')
|
.post('/api/accounting/make-journal-entries')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
|
journal_number: '1',
|
||||||
date: new Date('2020-1-1').toISOString(),
|
date: new Date('2020-1-1').toISOString(),
|
||||||
reference: '1000',
|
reference: '1000',
|
||||||
memo: 'Description here.',
|
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);
|
expect(foundAccountsTransactions.length).equals(2);
|
||||||
|
|
||||||
@@ -238,14 +241,14 @@ describe('routes: `/accounting`', () => {
|
|||||||
expect(foundAccountsTransactions[0].debit).equals(null);
|
expect(foundAccountsTransactions[0].debit).equals(null);
|
||||||
expect(foundAccountsTransactions[0].accountId).equals(account1.id);
|
expect(foundAccountsTransactions[0].accountId).equals(account1.id);
|
||||||
expect(foundAccountsTransactions[0].note).equals('First note');
|
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[0].userId).equals(1);
|
||||||
|
|
||||||
expect(foundAccountsTransactions[1].credit).equals(null);
|
expect(foundAccountsTransactions[1].credit).equals(null);
|
||||||
expect(foundAccountsTransactions[1].debit).equals(1000);
|
expect(foundAccountsTransactions[1].debit).equals(1000);
|
||||||
expect(foundAccountsTransactions[1].accountId).equals(account2.id);
|
expect(foundAccountsTransactions[1].accountId).equals(account2.id);
|
||||||
expect(foundAccountsTransactions[1].note).equals('Second note');
|
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);
|
expect(foundAccountsTransactions[1].userId).equals(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -255,17 +258,19 @@ describe('routes: `/accounting`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/manual-journal/1000')
|
.post('/api/manual-journal/1000')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should sumation of credit or debit be equal zero.', async () => {
|
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()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
@@ -292,11 +297,12 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should all credit and debit sumation be equal.', async () => {
|
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()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
journal_number: '123',
|
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 () => {
|
it('Should response journal number already exists in case another one on the storage.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const manualJournal2 = await create('manual_journal');
|
const manualJournal2 = await tenantFactory.create('manual_journal');
|
||||||
|
|
||||||
const jsonBody = {
|
const jsonBody = {
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
@@ -343,8 +349,9 @@ describe('routes: `/accounting`', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const res = await request()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
...jsonBody,
|
...jsonBody,
|
||||||
journal_number: manualJournal2.journalNumber,
|
journal_number: manualJournal2.journalNumber,
|
||||||
@@ -356,8 +363,8 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should not response journal number exists in case was unique number.', async () => {
|
it('Should not response journal number exists in case was unique number.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const manualJournal2 = await create('manual_journal');
|
const manualJournal2 = await tenantFactory.create('manual_journal');
|
||||||
|
|
||||||
const jsonBody = {
|
const jsonBody = {
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
@@ -376,8 +383,9 @@ describe('routes: `/accounting`', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
const res = await request()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
...jsonBody,
|
...jsonBody,
|
||||||
journal_number: manualJournal.journalNumber,
|
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 () => {
|
it('Should response error in case account id not exists in one of the given entries.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const manualJournal2 = await create('manual_journal');
|
const manualJournal2 = await tenantFactory.create('manual_journal');
|
||||||
|
|
||||||
const jsonBody = {
|
const jsonBody = {
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
@@ -410,8 +418,9 @@ describe('routes: `/accounting`', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
const res = await request()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
...jsonBody,
|
...jsonBody,
|
||||||
journal_number: manualJournal.journalNumber,
|
journal_number: manualJournal.journalNumber,
|
||||||
@@ -424,13 +433,14 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should update the given manual journal transaction in the storage.', async () => {
|
it('Should update the given manual journal transaction in the storage.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
date: new Date().toISOString(),
|
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);
|
.where('id', manualJournal.id);
|
||||||
|
|
||||||
expect(foundManualJournal.length).equals(1);
|
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 () => {
|
it('Should update account transactions that associated to the manual journal transaction.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
const transaction = await create('account_transaction', {
|
const transaction = await tenantFactory.create('account_transaction', {
|
||||||
reference_type: 'Journal',
|
reference_type: 'Journal',
|
||||||
reference_id: manualJournal.id,
|
reference_id: manualJournal.id,
|
||||||
});
|
});
|
||||||
const transaction2 = await create('account_transaction', {
|
const transaction2 = await tenantFactory.create('account_transaction', {
|
||||||
reference_type: 'Journal',
|
reference_type: 'Journal',
|
||||||
reference_id: manualJournal.id,
|
reference_id: manualJournal.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await request()
|
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('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
journal_number: '123',
|
journal_number: '123',
|
||||||
date: new Date().toISOString(),
|
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.length).equals(2);
|
||||||
expect(foundTransactions[0].credit).equals(0);
|
expect(foundTransactions[0].credit).equals(0);
|
||||||
@@ -516,6 +527,7 @@ describe('routes: `/accounting`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounting/manual-journals/1000')
|
.delete('/api/accounting/manual-journals/1000')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
@@ -525,33 +537,36 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete manual journal transactions from storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
|
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
const foundManualTransaction = await ManualJournal.query()
|
|
||||||
|
const foundManualTransaction = await ManualJournal.tenant().query()
|
||||||
.where('id', manualJournal.id).first();
|
.where('id', manualJournal.id).first();
|
||||||
|
|
||||||
expect(foundManualTransaction).equals(undefined);
|
expect(foundManualTransaction).equals(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete associated transactions of journal transaction.', async () => {
|
it('Should delete associated transactions of journal transaction.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal');
|
||||||
const transaction1 = await create('account_transaction', {
|
const transaction1 = await tenantFactory.create('account_transaction', {
|
||||||
reference_type: 'Journal', reference_id: manualJournal.id,
|
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,
|
reference_type: 'Journal', reference_id: manualJournal.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
|
.delete(`/api/accounting/manual-journals/${manualJournal.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const foundTransactions = await AccountTransaction.query();
|
const foundTransactions = await AccountTransaction.tenant().query();
|
||||||
expect(foundTransactions.length).equals(0);
|
expect(foundTransactions.length).equals(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -565,6 +580,7 @@ describe('routes: `/accounting`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounting/manual-journals/100')
|
.delete('/api/accounting/manual-journals/100')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
@@ -582,12 +598,13 @@ describe('routes: `/accounting`', () => {
|
|||||||
describe('route: `accounting/manual-journals`', async () => {
|
describe('route: `accounting/manual-journals`', async () => {
|
||||||
|
|
||||||
it('Should retrieve all manual journals with pagination meta.', async () => {
|
it('Should retrieve all manual journals with pagination meta.', async () => {
|
||||||
const manualJournal1 = await create('manual_journal');
|
const manualJournal1 = await tenantFactory.create('manual_journal');
|
||||||
const manualJournal2 = await create('manual_journal');
|
const manualJournal2 = await tenantFactory.create('manual_journal');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounting/manual-journals')
|
.get('/api/accounting/manual-journals')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
@@ -599,11 +616,12 @@ describe('routes: `/accounting`', () => {
|
|||||||
describe('route: POST `accounting/manual-journals/:id/publish`', () => {
|
describe('route: POST `accounting/manual-journals/:id/publish`', () => {
|
||||||
|
|
||||||
it('Should response not found in case the manual journal id was not exists.', async () => {
|
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()
|
const res = await request()
|
||||||
.post('/api/accounting/manual-journals/123/publish')
|
.post('/api/accounting/manual-journals/123/publish')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
@@ -613,10 +631,12 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response published ready.', async () => {
|
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()
|
const res = await request()
|
||||||
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
|
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(400);
|
expect(res.status).equals(400);
|
||||||
@@ -626,13 +646,13 @@ describe('routes: `/accounting`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should update all accounts transactions to not draft.', async () => {
|
it('Should update all accounts transactions to not draft.', async () => {
|
||||||
const manualJournal = await create('manual_journal');
|
const manualJournal = await tenantFactory.create('manual_journal', { status: 0 });
|
||||||
const transaction = await create('account_transaction', {
|
const transaction = await tenantFactory.create('account_transaction', {
|
||||||
reference_type: 'Journal',
|
reference_type: 'Journal',
|
||||||
reference_id: manualJournal.id,
|
reference_id: manualJournal.id,
|
||||||
draft: 1,
|
draft: 1,
|
||||||
});
|
});
|
||||||
const transaction2 = await create('account_transaction', {
|
const transaction2 = await tenantFactory.create('account_transaction', {
|
||||||
reference_type: 'Journal',
|
reference_type: 'Journal',
|
||||||
reference_id: manualJournal.id,
|
reference_id: manualJournal.id,
|
||||||
draft: 1,
|
draft: 1,
|
||||||
@@ -640,9 +660,10 @@ describe('routes: `/accounting`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
|
.post(`/api/accounting/manual-journals/${manualJournal.id}/publish`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const foundTransactions = await AccountTransaction.query()
|
const foundTransactions = await AccountTransaction.tenant().query()
|
||||||
.whereIn('id', [transaction.id, transaction2.id]);
|
.whereIn('id', [transaction.id, transaction2.id]);
|
||||||
|
|
||||||
expect(foundTransactions[0].draft).equals(0);
|
expect(foundTransactions[0].draft).equals(0);
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
import { request, expect, create, login } from '~/testInit';
|
import {
|
||||||
|
request,
|
||||||
|
expect,
|
||||||
|
} from '~/testInit';
|
||||||
import Account from '@/models/Account';
|
import Account from '@/models/Account';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: /accounts/', () => {
|
describe('routes: /accounts/', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
describe('POST `/accounts`', () => {
|
describe('POST `/accounts`', () => {
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
});
|
});
|
||||||
@@ -24,6 +27,7 @@ describe('routes: /accounts/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -34,6 +38,7 @@ describe('routes: /accounts/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
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 () => {
|
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()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Account Name',
|
name: 'Account Name',
|
||||||
description: account.description,
|
description: account.description,
|
||||||
@@ -59,10 +65,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should account code be unique in the storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: account.name,
|
name: account.name,
|
||||||
description: account.description,
|
description: account.description,
|
||||||
@@ -77,10 +84,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success with correct data form.', async () => {
|
it('Should response success with correct data form.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'description here',
|
description: 'description here',
|
||||||
@@ -93,9 +101,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should store account data in the storage.', async () => {
|
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')
|
const res = await request().post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Account Name',
|
name: 'Account Name',
|
||||||
description: 'desc here',
|
description: 'desc here',
|
||||||
@@ -103,12 +113,10 @@ describe('routes: /accounts/', () => {
|
|||||||
parent_account_id: account.id,
|
parent_account_id: account.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const accountModel = await Account.tenant().query()
|
||||||
|
|
||||||
const accountModel = await Account.query()
|
|
||||||
.where('name', 'Account Name')
|
.where('name', 'Account Name')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
expect(accountModel).a.an('object');
|
expect(accountModel).a.an('object');
|
||||||
expect(accountModel.description).equals('desc here');
|
expect(accountModel.description).equals('desc here');
|
||||||
expect(accountModel.accountTypeId).equals(account.accountTypeId);
|
expect(accountModel.accountTypeId).equals(account.accountTypeId);
|
||||||
@@ -118,10 +126,11 @@ describe('routes: /accounts/', () => {
|
|||||||
|
|
||||||
describe('POST `/accounts/:id`', () => {
|
describe('POST `/accounts/:id`', () => {
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/accounts/${account.id}`)
|
.post(`/api/accounts/${account.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -129,10 +138,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `account_type_id` be required.', async () => {
|
it('Should `account_type_id` be required.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/accounts/${account.id}`)
|
.post(`/api/accounts/${account.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -140,10 +150,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should max length of `code` be limited.', async () => {
|
it('Should max length of `code` be limited.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/accounts/${account.id}`)
|
.post(`/api/accounts/${account.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -154,17 +165,19 @@ describe('routes: /accounts/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should account code be unique in the storage.', async () => {
|
it('Should account code be unique in the storage.', async () => {
|
||||||
await create('account', { code: 'ABCD' });
|
await tenantFactory.create('account', { code: 'ABCD' });
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/accounts/${account.id}`)
|
.post(`/api/accounts/${account.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'name',
|
name: 'name',
|
||||||
code: 'ABCD',
|
code: 'ABCD',
|
||||||
@@ -178,10 +191,11 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success with correct data form.', async () => {
|
it('Should response success with correct data form.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/accounts')
|
.post('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
description: 'description here',
|
description: 'description here',
|
||||||
@@ -195,26 +209,15 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('GET: `/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 () => {
|
it('Should retrieve chart of accounts', async () => {
|
||||||
await create('resource', { name: 'accounts' });
|
await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
await create('account', { parent_account_id: account.id });
|
await tenantFactory.create('account', { parent_account_id: account.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
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 () => {
|
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',
|
label_name: 'Account type',
|
||||||
key: 'type',
|
key: 'type',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
@@ -232,28 +235,28 @@ describe('routes: /accounts/', () => {
|
|||||||
predefined: true,
|
predefined: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountNameField = await create('resource_field', {
|
const accountNameField = await tenantFactory.create('resource_field', {
|
||||||
label_name: 'Account Name',
|
label_name: 'Account Name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
active: true,
|
active: true,
|
||||||
predefined: true,
|
predefined: true,
|
||||||
});
|
});
|
||||||
const accountsView = await create('view', {
|
const accountsView = await tenantFactory.create('view', {
|
||||||
name: 'Accounts View',
|
name: 'Accounts View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '1 AND 2',
|
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,
|
view_id: accountsView.id,
|
||||||
index: 1,
|
index: 1,
|
||||||
field_id: accountTypeField.id,
|
field_id: accountTypeField.id,
|
||||||
value: accountType.name,
|
value: accountType.name,
|
||||||
comparator: 'equals',
|
comparator: 'equals',
|
||||||
});
|
});
|
||||||
await create('view_role', {
|
await tenantFactory.create('view_role', {
|
||||||
view_id: accountsView.id,
|
view_id: accountsView.id,
|
||||||
index: 2,
|
index: 2,
|
||||||
field_id: accountNameField.id,
|
field_id: accountNameField.id,
|
||||||
@@ -261,14 +264,17 @@ describe('routes: /accounts/', () => {
|
|||||||
comparator: 'contains',
|
comparator: 'contains',
|
||||||
});
|
});
|
||||||
|
|
||||||
await create('account', { name: 'account-1', account_type_id: accountType.id });
|
await tenantFactory.create('account', { name: 'account-1', account_type_id: accountType.id });
|
||||||
await create('account', { name: 'account-2', account_type_id: accountType.id });
|
await tenantFactory.create('account', { name: 'account-2', account_type_id: accountType.id });
|
||||||
await create('account', { name: 'account-3' });
|
await tenantFactory.create('account', { name: 'account-3' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.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();
|
.send();
|
||||||
|
|
||||||
expect(res.body.accounts.length).equals(2);
|
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 () => {
|
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',
|
label_name: 'Account type',
|
||||||
key: 'type',
|
key: 'type',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
active: true,
|
active: true,
|
||||||
predefined: true,
|
predefined: true,
|
||||||
});
|
});
|
||||||
const accountsView = await create('view', {
|
const accountsView = await tenantFactory.create('view', {
|
||||||
name: 'Accounts View',
|
name: 'Accounts View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '1',
|
roles_logic_expression: '1',
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountType = await create('account_type');
|
const accountType = await tenantFactory.create('account_type');
|
||||||
const accountsViewRole = await create('view_role', {
|
const accountsViewRole = await tenantFactory.create('view_role', {
|
||||||
view_id: accountsView.id,
|
view_id: accountsView.id,
|
||||||
index: 1,
|
index: 1,
|
||||||
field_id: accountTypeField.id,
|
field_id: accountTypeField.id,
|
||||||
@@ -303,13 +309,14 @@ describe('routes: /accounts/', () => {
|
|||||||
comparator: 'equals',
|
comparator: 'equals',
|
||||||
});
|
});
|
||||||
|
|
||||||
await create('account', { account_type_id: accountType.id });
|
await tenantFactory.create('account', { account_type_id: accountType.id });
|
||||||
await create('account');
|
await tenantFactory.create('account');
|
||||||
await create('account');
|
await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
custom_view_id: accountsView.id
|
custom_view_id: accountsView.id
|
||||||
})
|
})
|
||||||
@@ -320,15 +327,16 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve accounts and child accounts in nested set graph.', async () => {
|
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 account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account', { parent_account_id: account1.id });
|
const account2 = await tenantFactory.create('account', { parent_account_id: account1.id });
|
||||||
const account3 = await create('account', { parent_account_id: account2.id });
|
const account3 = await tenantFactory.create('account', { parent_account_id: account2.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({ display_type: 'tree' })
|
.query({ display_type: 'tree' })
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
@@ -346,15 +354,16 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve bad request when `filter_roles.*.field_key` not found in accounts resource.', async () => {
|
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 account1 = await tenantFactory.create('account', { name: 'ahmed' });
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
const account3 = await create('account');
|
const account3 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
stringified_filter_roles: JSON.stringify([{
|
stringified_filter_roles: JSON.stringify([{
|
||||||
condition: 'AND',
|
condition: 'AND',
|
||||||
@@ -379,27 +388,28 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve filtered accounts according to the given account type filter condition.', async () => {
|
it('Should retrieve filtered accounts according to the given account type filter condition.', async () => {
|
||||||
const resource = await create('resource', { name: 'accounts' });
|
const resource = await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const keyField = await create('resource_field', {
|
const keyField = await tenantFactory.create('resource_field', {
|
||||||
key: 'type',
|
key: 'type',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
});
|
});
|
||||||
const nameFiled = await create('resource_field', {
|
const nameFiled = await tenantFactory.create('resource_field', {
|
||||||
key: 'name',
|
key: 'name',
|
||||||
resource_id: resource.id,
|
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',
|
name: 'ahmed',
|
||||||
account_type_id: accountType.id
|
account_type_id: accountType.id
|
||||||
});
|
});
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
const account3 = await create('account');
|
const account3 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
stringified_filter_roles: JSON.stringify([{
|
stringified_filter_roles: JSON.stringify([{
|
||||||
condition: '&&',
|
condition: '&&',
|
||||||
@@ -418,19 +428,20 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Shoud retrieve filtered accounts according to the given account description filter condition.', async () => {
|
it('Shoud retrieve filtered accounts according to the given account description filter condition.', async () => {
|
||||||
const resource = await create('resource', { name: 'accounts' });
|
const resource = await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
key: 'description',
|
key: 'description',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const account1 = await create('account', { name: 'ahmed', description: 'here' });
|
const account1 = await tenantFactory.create('account', { name: 'ahmed', description: 'here' });
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
const account3 = await create('account');
|
const account3 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
stringified_filter_roles: JSON.stringify([{
|
stringified_filter_roles: JSON.stringify([{
|
||||||
condition: 'AND',
|
condition: 'AND',
|
||||||
@@ -445,24 +456,25 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve filtered accounts based on given filter roles between OR conditions.', async () => {
|
it('Should retrieve filtered accounts based on given filter roles between OR conditions.', async () => {
|
||||||
const resource = await create('resource', { name: 'accounts' });
|
const resource = await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
key: 'description',
|
key: 'description',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const resourceCodeField = await create('resource_field', {
|
const resourceCodeField = await tenantFactory.create('resource_field', {
|
||||||
key: 'code',
|
key: 'code',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const account1 = await create('account', { name: 'ahmed', description: 'target' });
|
const account1 = await tenantFactory.create('account', { name: 'ahmed', description: 'target' });
|
||||||
const account2 = await create('account', { description: 'target' });
|
const account2 = await tenantFactory.create('account', { description: 'target' });
|
||||||
const account3 = await create('account');
|
const account3 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
stringified_filter_roles: JSON.stringify([{
|
stringified_filter_roles: JSON.stringify([{
|
||||||
condition: '&&',
|
condition: '&&',
|
||||||
@@ -484,26 +496,26 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve filtered accounts from custom view and filter roles.', async () => {
|
it('Should retrieve filtered accounts from custom view and filter roles.', 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', {
|
||||||
key: 'type', resource_id: resource.id,
|
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,
|
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 account1 = await tenantFactory.create('account', { name: 'ahmed-1' });
|
||||||
const account2 = await create('account', { name: 'ahmed-2', account_type_id: accountType.id, description: 'target' });
|
const account2 = await tenantFactory.create('account', { name: 'ahmed-2', account_type_id: accountType.id, description: 'target' });
|
||||||
const account3 = await create('account', { name: 'ahmed-3' });
|
const account3 = await tenantFactory.create('account', { name: 'ahmed-3' });
|
||||||
|
|
||||||
const accountsView = await create('view', {
|
const accountsView = await tenantFactory.create('view', {
|
||||||
name: 'Accounts View',
|
name: 'Accounts View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '1',
|
roles_logic_expression: '1',
|
||||||
});
|
});
|
||||||
const accountsViewRole = await create('view_role', {
|
const accountsViewRole = await tenantFactory.create('view_role', {
|
||||||
view_id: accountsView.id,
|
view_id: accountsView.id,
|
||||||
field_id: accountTypeField.id,
|
field_id: accountTypeField.id,
|
||||||
index: 1,
|
index: 1,
|
||||||
@@ -514,6 +526,7 @@ describe('routes: /accounts/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
custom_view_id: accountsView.id,
|
custom_view_id: accountsView.id,
|
||||||
stringified_filter_roles: JSON.stringify([{
|
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 () => {
|
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()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
column_sort_order: 'not_found',
|
column_sort_by: 'not_found',
|
||||||
sort_order: 'desc',
|
sort_order: 'desc',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -545,18 +559,19 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should sorting the given `column_sort_order` column on asc direction,', async () => {
|
it('Should sorting the given `column_sort_order` column on asc direction,', async () => {
|
||||||
const resource = await create('resource', { name: 'accounts' });
|
const resource = await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
key: 'name', resource_id: resource.id,
|
key: 'name', resource_id: resource.id,
|
||||||
});
|
});
|
||||||
const accounts1 = await create('account', { name: 'A' });
|
const accounts1 = await tenantFactory.create('account', { name: 'A' });
|
||||||
const accounts2 = await create('account', { name: 'B' });
|
const accounts2 = await tenantFactory.create('account', { name: 'B' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
column_sort_order: 'name',
|
column_sort_by: 'name',
|
||||||
sort_order: 'asc',
|
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 () => {
|
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 resource = await tenantFactory.create('resource', { name: 'accounts' });
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
key: 'type', resource_id: resource.id,
|
key: 'type', resource_id: resource.id,
|
||||||
});
|
});
|
||||||
const accounts1 = await create('account', { name: 'A' });
|
const accounts1 = await tenantFactory.create('account', { name: 'A' });
|
||||||
const accounts2 = await create('account', { name: 'B' });
|
const accounts2 = await tenantFactory.create('account', { name: 'B' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/accounts')
|
.get('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
column_sort_order: 'name',
|
column_sort_by: 'name',
|
||||||
sort_order: 'asc',
|
sort_order: 'asc',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.body.accounts[0].name).equals('A');
|
expect(res.body.accounts[0].name).equals('A');
|
||||||
expect(res.body.accounts[1].name).equals('B');
|
expect(res.body.accounts[1].name).equals('B');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('DELETE: `/accounts`', () => {
|
describe('DELETE: `/accounts`', () => {
|
||||||
@@ -593,28 +608,31 @@ describe('routes: /accounts/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounts/10')
|
.delete('/api/accounts/10')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the give account from the storage.', async () => {
|
it('Should delete the give account from the storage.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
await request()
|
await request()
|
||||||
.delete(`/api/accounts/${account.id}`)
|
.delete(`/api/accounts/${account.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.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);
|
expect(foundAccounts).to.have.lengthOf(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should not delete the given account in case account has associated transactions.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/accounts/${accountTransaction.accountId}`)
|
.delete(`/api/accounts/${accountTransaction.accountId}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(400);
|
expect(res.status).equals(400);
|
||||||
@@ -624,12 +642,12 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('DELETE: `/accounts?ids=`', () => {
|
describe('DELETE: `/accounts?ids=`', () => {
|
||||||
it('Should response in case on of accounts ids was not exists.', async () => {
|
it('Should response in case on of accounts ids was not exists.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounts')
|
.delete('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
ids: [100, 200],
|
ids: [100, 200],
|
||||||
})
|
})
|
||||||
@@ -642,31 +660,33 @@ describe('routes: /accounts/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response bad request in case one of accounts has transactions.', async () => {
|
it('Should response bad request in case one of accounts has transactions.', async () => {
|
||||||
const accountTransaction = await create('account_transaction');
|
const accountTransaction = await tenantFactory.create('account_transaction');
|
||||||
const accountTransaction2 = await create('account_transaction');
|
const accountTransaction2 = await tenantFactory.create('account_transaction');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounts')
|
.delete('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
ids: [accountTransaction.accountId, accountTransaction2.accountId],
|
ids: [accountTransaction.accountId, accountTransaction2.accountId],
|
||||||
})
|
})
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.errors).include.something.that.deep.equals({
|
expect(res.body.errors).include.something.that.deep.equals({
|
||||||
type: 'ACCOUNTS.HAS.TRANSACTIONS',
|
type: 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS',
|
||||||
code: 300,
|
code: 300,
|
||||||
ids: [accountTransaction.accountId, accountTransaction2.accountId],
|
ids: [accountTransaction.accountId, accountTransaction2.accountId],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the given accounts from the storage.', async () => {
|
it('Should delete the given accounts from the storage.', async () => {
|
||||||
const account1 = await create('account');
|
const account1 = await tenantFactory.create('account');
|
||||||
const account2 = await create('account');
|
const account2 = await tenantFactory.create('account');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/accounts')
|
.delete('/api/accounts')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
ids: [account1.id, account2.id],
|
ids: [account1.id, account2.id],
|
||||||
})
|
})
|
||||||
@@ -674,9 +694,66 @@ describe('routes: /accounts/', () => {
|
|||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
|
|
||||||
const foundAccounts = await Account.query()
|
const foundAccounts = await Account.tenant().query()
|
||||||
.whereIn('id', [account1.id, account2.id]);
|
.whereIn('id', [account1.id, account2.id]);
|
||||||
|
|
||||||
expect(foundAccounts.length).equals(0);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
import { request, expect, create } from '~/testInit';
|
import { request, expect, createUser } from '~/testInit';
|
||||||
import { hashPassword } from '@/utils';
|
import { hashPassword } from '@/utils';
|
||||||
import knex from '@/database/knex';
|
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('routes: /auth/', () => {
|
||||||
describe('POST `/api/auth/login`', () => {
|
describe('POST `/api/auth/login`', () => {
|
||||||
@@ -59,33 +69,35 @@ describe('routes: /auth/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should not authenticate in case user was not active.', async () => {
|
it('Should not authenticate in case user was not active.', async () => {
|
||||||
const user = await create('user', { active: false });
|
const user = await createUser(tenantWebsite, {
|
||||||
const res = await request().post('/api/auth/login').send({
|
active: false,
|
||||||
crediential: user.email,
|
email: 'admin@admin.com',
|
||||||
password: 'incorrect_password',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const res = await request().post('/api/auth/login').send({
|
||||||
|
crediential: 'admin@admin.com',
|
||||||
|
password: 'admin',
|
||||||
|
});
|
||||||
expect(res.status).equals(400);
|
expect(res.status).equals(400);
|
||||||
expect(res.body.errors).include.something.that.deep.equals({
|
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 () => {
|
it('Should authenticate with correct email and password and active user.', async () => {
|
||||||
const user = await create('user', {
|
const user = await createUser(tenantWebsite, {
|
||||||
password: hashPassword('admin'),
|
email: 'admin@admin.com',
|
||||||
});
|
});
|
||||||
const res = await request().post('/api/auth/login').send({
|
const res = await request().post('/api/auth/login').send({
|
||||||
crediential: user.email,
|
crediential: user.email,
|
||||||
password: 'admin',
|
password: 'admin',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should autheticate success with correct phone number and password.', async () => {
|
it('Should autheticate success with correct phone number and password.', async () => {
|
||||||
const password = await hashPassword('admin');
|
const password = await hashPassword('admin');
|
||||||
const user = await create('user', {
|
const user = await createUser(tenantWebsite, {
|
||||||
phone_number: '0920000000',
|
phone_number: '0920000000',
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
@@ -98,15 +110,20 @@ describe('routes: /auth/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should last login date be saved after success login.', async () => {
|
it('Should last login date be saved after success login.', async () => {
|
||||||
const user = await create('user', {
|
const user = await createUser(tenantWebsite, {
|
||||||
password: hashPassword('admin'),
|
email: 'admin@admin.com',
|
||||||
});
|
});
|
||||||
const res = await request().post('/api/auth/login').send({
|
const res = await request().post('/api/auth/login').send({
|
||||||
crediential: user.email,
|
crediential: user.email,
|
||||||
password: 'admin',
|
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(res.status).equals(200);
|
||||||
|
expect(foundUserAfterUpdate.lastLoginAt).to.not.be.null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -132,17 +149,18 @@ describe('routes: /auth/', () => {
|
|||||||
email: 'admin@admin.com',
|
email: 'admin@admin.com',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(400);
|
||||||
expect(res.body.errors).include.something.that.deep.equals({
|
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 () => {
|
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';
|
const token = '123123';
|
||||||
|
|
||||||
await knex('password_resets').insert({ email: user.email, token });
|
await knex('password_resets').insert({ email: user.email, token });
|
||||||
|
|
||||||
await request().post('/api/auth/send_reset_password').send({
|
await request().post('/api/auth/send_reset_password').send({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
});
|
});
|
||||||
@@ -153,7 +171,7 @@ describe('routes: /auth/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should store new token associate with the given email.', async () => {
|
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({
|
await request().post('/api/auth/send_reset_password').send({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
});
|
});
|
||||||
@@ -164,7 +182,7 @@ describe('routes: /auth/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success if the email was exist.', async () => {
|
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({
|
const res = await request().post('/api/auth/send_reset_password').send({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
});
|
});
|
||||||
@@ -183,63 +201,88 @@ describe('routes: /auth/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `password` be required.', async () => {
|
it('Should `password` be required.', async () => {
|
||||||
const passwordReset = await create('password_reset');
|
const user = await createUser(tenantWebsite);
|
||||||
const res = await request().post(`/api/reset/${passwordReset.token}`).send();
|
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.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);
|
const paramsErrors = res.body.errors.map((error) => error.param);
|
||||||
expect(paramsErrors).to.include('password');
|
expect(paramsErrors).to.include('password');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should password and confirm_password be equal.', async () => {
|
it('Should password and confirm_password be equal.', async () => {
|
||||||
const passwordReset = await create('password_reset');
|
const user = await createUser(tenantWebsite);
|
||||||
const res = await request().post(`/api/reset/${passwordReset.token}`).send({
|
const passwordReset = await systemFactory.create('password_reset', {
|
||||||
password: '123123',
|
email: user.email,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const res = await request()
|
||||||
|
.post(`/api/auth/reset/${passwordReset.token}`)
|
||||||
|
.send({
|
||||||
|
password: '123123',
|
||||||
|
});
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
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);
|
const paramsErrors = res.body.errors.map((error) => error.param);
|
||||||
expect(paramsErrors).to.include('password');
|
expect(paramsErrors).to.include('password');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success with correct data form.', async () => {
|
it('Should response success with correct data form.', async () => {
|
||||||
const passwordReset = await create('password_reset');
|
const user = await createUser(tenantWebsite);
|
||||||
const res = await request().post(`/api/reset/${passwordReset.token}`).send({
|
const passwordReset = await systemFactory.create('password_reset', {
|
||||||
password: '123123',
|
email: user.email,
|
||||||
confirm_password: '123123',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const res = await request()
|
||||||
|
.post(`/api/auth/reset/${passwordReset.token}`)
|
||||||
|
.send({
|
||||||
|
password: '123123',
|
||||||
|
confirm_password: '123123',
|
||||||
|
});
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should token be deleted after success response.', async () => {
|
it('Should token be deleted after success response.', async () => {
|
||||||
const passwordReset = await create('password_reset');
|
const user = await createUser(tenantWebsite);
|
||||||
await request().post(`/api/reset/${passwordReset.token}`).send({
|
const passwordReset = await systemFactory.create('password_reset', {
|
||||||
password: '123123',
|
email: user.email,
|
||||||
confirm_password: '123123',
|
|
||||||
});
|
});
|
||||||
|
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);
|
expect(foundTokens).to.have.lengthOf(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should password be updated after success response.', async () => {
|
it('Should password be updated after success response.', async () => {
|
||||||
const user = await create('user');
|
const user = await createUser(tenantWebsite);
|
||||||
const passwordReset = await create('password_reset', { user_id: user.id });
|
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',
|
password: '123123',
|
||||||
confirm_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(systemUserPasswordUpdated.id).equals(user.id);
|
||||||
|
expect(systemUserPasswordUpdated.password).not.equals(user.password);
|
||||||
expect(foundUser.id).equals(user.id);
|
|
||||||
expect(foundUser.password).not.equals(user.password);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,36 +1,31 @@
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
create,
|
|
||||||
expect,
|
expect,
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import Currency from '@/models/Currency';
|
import Currency from '@/models/Currency';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('route: /currencies/', () => {
|
describe('route: /currencies/', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('POST: `/api/currencies`', () => {
|
describe('POST: `/api/currencies`', () => {
|
||||||
|
|
||||||
it('Should response unauthorized in case user was not logged in.', async () => {
|
it('Should response unauthorized in case user was not logged in.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `currency_name` be required.', async () => {
|
it('Should `currency_name` be required.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -44,6 +39,7 @@ describe('route: /currencies/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -54,11 +50,12 @@ describe('route: /currencies/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response currency code is duplicated.', async () => {
|
it('Should response currency code is duplicated.', async () => {
|
||||||
create('currency', { currency_code: 'USD' });
|
tenantFactory.create('currency', { currency_code: 'USD' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
currency_name: 'Dollar',
|
currency_name: 'Dollar',
|
||||||
@@ -74,12 +71,13 @@ describe('route: /currencies/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
currency_name: 'Dollar',
|
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.length).equals(1);
|
||||||
expect(foundCurrency[0].currencyCode).equals('USD');
|
expect(foundCurrency[0].currencyCode).equals('USD');
|
||||||
@@ -90,6 +88,7 @@ describe('route: /currencies/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/currencies')
|
.post('/api/currencies')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
currency_name: 'Dollar',
|
currency_name: 'Dollar',
|
||||||
@@ -100,27 +99,28 @@ describe('route: /currencies/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('DELETE: `/api/currencies/:currency_code`', () => {
|
describe('DELETE: `/api/currencies/:currency_code`', () => {
|
||||||
|
|
||||||
it('Should delete the given currency code from the storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/currencies/${currency.currencyCode}`)
|
.delete(`/api/currencies/${currency.currencyCode}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
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);
|
expect(foundCurrency.length).equals(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('POST: `/api/currencies/:id`', () => {
|
describe('POST: `/api/currencies/:id`', () => {
|
||||||
it('Should `currency_name` be required.', async () => {
|
it('Should `currency_name` be required.', async () => {
|
||||||
const currency = await create('currency');
|
const currency = await tenantFactory.create('currency');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/currencies/${currency.code}`)
|
.post(`/api/currencies/${currency.code}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -131,10 +131,11 @@ describe('route: /currencies/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `currency_code` be required.', async () => {
|
it('Should `currency_code` be required.', async () => {
|
||||||
const currency = await create('currency');
|
const currency = await tenantFactory.create('currency');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/currencies/${currency.code}`)
|
.post(`/api/currencies/${currency.code}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -145,12 +146,13 @@ describe('route: /currencies/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response currency code is duplicated.', async () => {
|
it('Should response currency code is duplicated.', async () => {
|
||||||
const currency1 = await create('currency');
|
const currency1 = await tenantFactory.create('currency');
|
||||||
const currency2 = await create('currency');
|
const currency2 = await tenantFactory.create('currency');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/currencies/${currency2.id}`)
|
.post(`/api/currencies/${currency2.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
currency_code: currency1.currencyCode,
|
currency_code: currency1.currencyCode,
|
||||||
currency_name: 'Dollar',
|
currency_name: 'Dollar',
|
||||||
@@ -163,18 +165,19 @@ describe('route: /currencies/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should update currency details of the given currency on the storage.', async () => {
|
it('Should update currency details of the given currency on the storage.', async () => {
|
||||||
const currency1 = await create('currency');
|
const currency1 = await tenantFactory.create('currency');
|
||||||
const currency2 = await create('currency');
|
const currency2 = await tenantFactory.create('currency');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/currencies/${currency2.id}`)
|
.post(`/api/currencies/${currency2.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
currency_code: 'ABC',
|
currency_code: 'ABC',
|
||||||
currency_name: 'Name',
|
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.length).equals(1);
|
||||||
expect(foundCurrency[0].currencyCode).equals('ABC');
|
expect(foundCurrency[0].currencyCode).equals('ABC');
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
create,
|
|
||||||
expect,
|
expect,
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import ExchangeRate from '../../src/models/ExchangeRate';
|
import ExchangeRate from '../../src/models/ExchangeRate';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe.only('route: /exchange_rates/', () => {
|
describe('route: /exchange_rates/', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
describe('POST: `/api/exchange_rates`', () => {
|
describe('POST: `/api/exchange_rates`', () => {
|
||||||
it('Should response unauthorized in case the user was not logged in.', async () => {
|
it('Should response unauthorized in case the user was not logged in.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
@@ -23,13 +19,14 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `currency_code` be required.', async () => {
|
it('Should `currency_code` be required.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates')
|
.post('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -43,6 +40,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates')
|
.post('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -56,6 +54,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates')
|
.post('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
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 () => {
|
it('Should response date and currency code is already exists.', async () => {
|
||||||
await create('exchange_rate', {
|
await tenantFactory.create('exchange_rate', {
|
||||||
date: '2020-02-02',
|
date: '2020-02-02',
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
exchange_rate: 4.4,
|
exchange_rate: 4.4,
|
||||||
@@ -74,6 +73,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates')
|
.post('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: '2020-02-02',
|
date: '2020-02-02',
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
@@ -90,6 +90,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates')
|
.post('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: '2020-02-02',
|
date: '2020-02-02',
|
||||||
currency_code: 'USD',
|
currency_code: 'USD',
|
||||||
@@ -97,7 +98,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
});
|
});
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
|
|
||||||
const foundExchangeRate = await ExchangeRate.query()
|
const foundExchangeRate = await ExchangeRate.tenant().query()
|
||||||
.where('currency_code', 'USD');
|
.where('currency_code', 'USD');
|
||||||
|
|
||||||
expect(foundExchangeRate.length).equals(1);
|
expect(foundExchangeRate.length).equals(1);
|
||||||
@@ -111,13 +112,14 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
|
|
||||||
describe('GET: `/api/exchange_rates', () => {
|
describe('GET: `/api/exchange_rates', () => {
|
||||||
it('Should retrieve all exchange rates with pagination meta.', async () => {
|
it('Should retrieve all exchange rates with pagination meta.', async () => {
|
||||||
await create('exchange_rate');
|
await tenantFactory.create('exchange_rate');
|
||||||
await create('exchange_rate');
|
await tenantFactory.create('exchange_rate');
|
||||||
await create('exchange_rate');
|
await tenantFactory.create('exchange_rate');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/exchange_rates')
|
.get('/api/exchange_rates')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
@@ -130,6 +132,7 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/exchange_rates/100')
|
.post('/api/exchange_rates/100')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
date: '2020-02-02',
|
date: '2020-02-02',
|
||||||
currency_code: 'USD',
|
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 () => {
|
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()
|
const res = await request()
|
||||||
.post(`/api/exchange_rates/${exRate.id}`)
|
.post(`/api/exchange_rates/${exRate.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
exchange_rate: 4.4,
|
exchange_rate: 4.4,
|
||||||
});
|
});
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
|
|
||||||
const foundExchangeRate = await ExchangeRate.query()
|
const foundExchangeRate = await ExchangeRate.tenant().query()
|
||||||
.where('id', exRate.id);
|
.where('id', exRate.id);
|
||||||
|
|
||||||
expect(foundExchangeRate.length).equals(1);
|
expect(foundExchangeRate.length).equals(1);
|
||||||
@@ -165,7 +169,9 @@ describe.only('route: /exchange_rates/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/exchange_rates/100')
|
.delete('/api/exchange_rates/100')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
expect(res.body.errors).include.something.deep.equals({
|
expect(res.body.errors).include.something.deep.equals({
|
||||||
type: 'EXCHANGE.RATE.NOT.FOUND', code: 200,
|
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 () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/exchange_rates/${exRate.id}`)
|
.delete(`/api/exchange_rates/${exRate.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const foundRates = await ExchangeRate.query();
|
const foundRates = await ExchangeRate.tenant().query();
|
||||||
expect(foundRates.length).equals(0);
|
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);
|
||||||
|
})
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,57 +1,68 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
expect,
|
|
||||||
request,
|
request,
|
||||||
|
expect,
|
||||||
login,
|
login,
|
||||||
create,
|
createTenantFactory,
|
||||||
|
createTenant,
|
||||||
|
dropTenant,
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
|
|
||||||
|
let tenantWebsite;
|
||||||
|
let tenantFactory;
|
||||||
let loginRes;
|
let loginRes;
|
||||||
let creditAccount;
|
let creditAccount;
|
||||||
let debitAccount;
|
let debitAccount;
|
||||||
|
|
||||||
describe('routes: `/financial_statements`', () => {
|
describe('routes: `/financial_statements`', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
loginRes = await login();
|
tenantWebsite = await createTenant();
|
||||||
|
tenantFactory = createTenantFactory(tenantWebsite.tenantDb);
|
||||||
|
|
||||||
|
loginRes = await login(tenantWebsite);
|
||||||
|
|
||||||
// Balance sheet types.
|
// Balance sheet types.
|
||||||
const creditAccType = await create('account_type', { normal: 'credit', balance_sheet: true });
|
const creditAccType = await tenantFactory.create('account_type', { normal: 'credit', balance_sheet: true });
|
||||||
const debitAccType = await create('account_type', { normal: 'debit', balance_sheet: true });
|
const debitAccType = await tenantFactory.create('account_type', { normal: 'debit', balance_sheet: true });
|
||||||
|
|
||||||
// Income statement types.
|
// Income statement types.
|
||||||
const incomeType = await create('account_type', { normal: 'credit', income_sheet: true });
|
const incomeType = await tenantFactory.create('account_type', { normal: 'credit', income_sheet: true });
|
||||||
const expenseType = await create('account_type', { normal: 'debit', income_sheet: true });
|
const expenseType = await tenantFactory.create('account_type', { normal: 'debit', income_sheet: true });
|
||||||
|
|
||||||
// Assets & liabilites accounts.
|
// Assets & liabilites accounts.
|
||||||
creditAccount = await create('account', { account_type_id: creditAccType.id });
|
creditAccount = await tenantFactory.create('account', { account_type_id: creditAccType.id });
|
||||||
debitAccount = await create('account', { account_type_id: debitAccType.id });
|
debitAccount = await tenantFactory.create('account', { account_type_id: debitAccType.id });
|
||||||
|
|
||||||
// Income && expenses accounts.
|
// Income && expenses accounts.
|
||||||
const incomeAccount = await create('account', { account_type_id: incomeType.id });
|
const incomeAccount = await tenantFactory.create('account', { account_type_id: incomeType.id });
|
||||||
const expenseAccount = await create('account', { account_type_id: expenseType.id });
|
const expenseAccount = await tenantFactory.create('account', { account_type_id: expenseType.id });
|
||||||
const income2Account = await create('account', { account_type_id: incomeType.id });
|
const income2Account = await tenantFactory.create('account', { account_type_id: incomeType.id });
|
||||||
|
|
||||||
const accountTransactionMixied = { date: '2020-1-10' };
|
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,
|
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,
|
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,
|
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,
|
debit: 2000, credit: 0, account_id: debitAccount.id, ...accountTransactionMixied,
|
||||||
});
|
});
|
||||||
await create('account_transaction', { credit: 2000, account_id: incomeAccount.id, ...accountTransactionMixied });
|
await tenantFactory.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', { debit: 6000, account_id: expenseAccount.id, ...accountTransactionMixied });
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(async () => {
|
||||||
|
await dropTenant(tenantWebsite);
|
||||||
|
|
||||||
loginRes = null;
|
loginRes = null;
|
||||||
|
tenantFactory = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('routes: `/financial_statements/journal`', () => {
|
describe('routes: `/financial_statements/journal`', () => {
|
||||||
it('Should response unauthorized in case the user was not authorized.', async () => {
|
it('Should response unauthorized in case the user was not authorized.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
@@ -65,6 +76,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
@@ -83,6 +95,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2018-01-01',
|
from_date: '2018-01-01',
|
||||||
to_date: '2019-01-01',
|
to_date: '2019-01-01',
|
||||||
@@ -96,6 +109,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
account_ids: [creditAccount.id],
|
account_ids: [creditAccount.id],
|
||||||
})
|
})
|
||||||
@@ -108,6 +122,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
transaction_types: ['Expense'],
|
transaction_types: ['Expense'],
|
||||||
});
|
});
|
||||||
@@ -119,6 +134,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_range: 2000,
|
from_range: 2000,
|
||||||
to_range: 2000,
|
to_range: 2000,
|
||||||
@@ -140,6 +156,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/journal')
|
.get('/api/financial_statements/journal')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
number_format: {
|
number_format: {
|
||||||
divide_1000: true,
|
divide_1000: true,
|
||||||
@@ -167,6 +184,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.query.from_date).equals(moment().startOf('year').format('YYYY-MM-DD'));
|
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()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.accounts).is.an('array');
|
expect(res.body.accounts).is.an('array');
|
||||||
@@ -201,6 +220,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const targetAccount = res.body.accounts.find((a) => a.id === creditAccount.id);
|
const targetAccount = res.body.accounts.find((a) => a.id === creditAccount.id);
|
||||||
@@ -218,6 +238,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-20',
|
from_date: '2020-01-20',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -240,6 +261,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
none_zero: true,
|
none_zero: true,
|
||||||
})
|
})
|
||||||
@@ -262,6 +284,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-20',
|
from_date: '2020-01-20',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -277,6 +300,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-20',
|
from_date: '2020-01-20',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -293,6 +317,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -311,6 +336,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2020-03-30',
|
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 () => {
|
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',
|
debit: 0.25, credit: 0, account_id: debitAccount.id, date: '2020-1-10',
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -351,6 +378,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/general_ledger')
|
.get('/api/financial_statements/general_ledger')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2020-03-30',
|
to_date: '2020-03-30',
|
||||||
@@ -376,6 +404,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'year',
|
display_columns_by: 'year',
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
@@ -397,6 +426,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'year',
|
display_columns_by: 'year',
|
||||||
})
|
})
|
||||||
@@ -410,6 +440,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_type: 'total',
|
display_columns_type: 'total',
|
||||||
from_date: '2012-01-01',
|
from_date: '2012-01-01',
|
||||||
@@ -431,6 +462,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'year',
|
display_columns_by: 'year',
|
||||||
from_date: '2012-01-01',
|
from_date: '2012-01-01',
|
||||||
@@ -484,6 +516,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'day',
|
display_columns_by: 'day',
|
||||||
from_date: '2020-01-08',
|
from_date: '2020-01-08',
|
||||||
@@ -504,6 +537,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'month',
|
display_columns_by: 'month',
|
||||||
from_date: '2019-07-01',
|
from_date: '2019-07-01',
|
||||||
@@ -534,6 +568,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'quarter',
|
display_columns_by: 'quarter',
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
@@ -551,12 +586,13 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve the balance sheet amounts without cents.', async () => {
|
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',
|
debit: 0.25, credit: 0, account_id: debitAccount.id, date: '2020-1-10',
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'quarter',
|
display_columns_by: 'quarter',
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
@@ -580,6 +616,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'quarter',
|
display_columns_by: 'quarter',
|
||||||
from_date: '2020',
|
from_date: '2020',
|
||||||
@@ -603,6 +640,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/balance_sheet')
|
.get('/api/financial_statements/balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
display_columns_by: 'quarter',
|
display_columns_by: 'quarter',
|
||||||
from_date: '2002',
|
from_date: '2002',
|
||||||
@@ -632,6 +670,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/trial_balance_sheet')
|
.get('/api/financial_statements/trial_balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const foundCreditAccount = res.body.items.find((item) => {
|
const foundCreditAccount = res.body.items.find((item) => {
|
||||||
@@ -646,6 +685,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/trial_balance_sheet')
|
.get('/api/financial_statements/trial_balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
// There is no transactions between these dates.
|
// There is no transactions between these dates.
|
||||||
from_date: '2002-01-01',
|
from_date: '2002-01-01',
|
||||||
@@ -661,6 +701,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/trial_balance_sheet')
|
.get('/api/financial_statements/trial_balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
// There is no transactions between these dates.
|
// There is no transactions between these dates.
|
||||||
from_date: '2020-01-05',
|
from_date: '2020-01-05',
|
||||||
@@ -680,6 +721,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/trial_balance_sheet')
|
.get('/api/financial_statements/trial_balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
// There is no transactions between these dates.
|
// There is no transactions between these dates.
|
||||||
from_date: '2020-01-05',
|
from_date: '2020-01-05',
|
||||||
@@ -702,6 +744,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/trial_balance_sheet')
|
.get('/api/financial_statements/trial_balance_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
// There is no transactions between these dates.
|
// There is no transactions between these dates.
|
||||||
from_date: '2020-01-05',
|
from_date: '2020-01-05',
|
||||||
@@ -732,6 +775,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2020-12-12',
|
to_date: '2020-12-12',
|
||||||
@@ -755,6 +799,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: moment().startOf('year').format('YYYY-MM-DD'),
|
from_date: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
to_date: moment().endOf('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()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
||||||
to_date: moment('2020-01-01').endOf('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()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
||||||
to_date: moment('2020-01-01').endOf('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()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
from_date: moment('2020-01-01').startOf('month').format('YYYY-MM-DD'),
|
||||||
to_date: toDate,
|
to_date: toDate,
|
||||||
@@ -838,6 +886,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2021-01-01',
|
to_date: '2021-01-01',
|
||||||
@@ -854,6 +903,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2021-01-01',
|
to_date: '2021-01-01',
|
||||||
@@ -870,6 +920,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2019-12-01',
|
from_date: '2019-12-01',
|
||||||
to_date: '2020-12-01',
|
to_date: '2020-12-01',
|
||||||
@@ -887,6 +938,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2019-12-01',
|
from_date: '2019-12-01',
|
||||||
to_date: '2020-12-01',
|
to_date: '2020-12-01',
|
||||||
@@ -904,6 +956,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2019-12-01',
|
from_date: '2019-12-01',
|
||||||
to_date: '2020-12-01',
|
to_date: '2020-12-01',
|
||||||
@@ -920,6 +973,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2019-12-01',
|
from_date: '2019-12-01',
|
||||||
to_date: '2020-12-01',
|
to_date: '2020-12-01',
|
||||||
@@ -942,6 +996,7 @@ describe('routes: `/financial_statements`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/financial_statements/profit_loss_sheet')
|
.get('/api/financial_statements/profit_loss_sheet')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
from_date: '2020-01-01',
|
from_date: '2020-01-01',
|
||||||
to_date: '2021-01-01',
|
to_date: '2021-01-01',
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
create,
|
|
||||||
expect,
|
expect,
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import knex from '@/database/knex';
|
|
||||||
import Item from '@/models/Item';
|
import Item from '@/models/Item';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: `/items`', () => {
|
describe('routes: `/items`', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
describe('POST: `/items`', () => {
|
describe('POST: `/items`', () => {
|
||||||
it('Should not create a new item if the user was not authorized.', async () => {
|
it('Should not create a new item if the user was not authorized.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
@@ -23,21 +18,14 @@ describe('routes: `/items`', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
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 () => {
|
it('Should `name` be required.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -51,6 +39,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -64,6 +53,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
type: 'not-defined',
|
type: 'not-defined',
|
||||||
});
|
});
|
||||||
@@ -80,6 +70,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
cost_price: 'not_numeric',
|
cost_price: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -98,6 +89,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
sell_price: 'not_numeric',
|
sell_price: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -116,6 +108,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
cost_account_id: 'not_numeric',
|
cost_account_id: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -134,6 +127,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
sell_account_id: 'not_numeric',
|
sell_account_id: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -160,6 +154,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'inventory',
|
type: 'inventory',
|
||||||
@@ -180,6 +175,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -200,6 +196,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -219,6 +216,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -238,6 +236,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -255,13 +254,14 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success with correct data format.', async () => {
|
it('Should response success with correct data format.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const anotherAccount = await create('account');
|
const anotherAccount = await tenantFactory.create('account');
|
||||||
const itemCategory = await create('item_category');
|
const itemCategory = await tenantFactory.create('item_category');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items')
|
.post('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -274,6 +274,42 @@ describe('routes: `/items`', () => {
|
|||||||
|
|
||||||
expect(res.status).equals(200);
|
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`', () => {
|
describe('POST: `items/:id`', () => {
|
||||||
@@ -281,6 +317,7 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/items/100')
|
.post('/api/items/100')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'product',
|
type: 'product',
|
||||||
@@ -298,10 +335,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -312,10 +350,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `type` be required.', async () => {
|
it('Should `type` be required.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -326,10 +365,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `sell_price` be numeric.', async () => {
|
it('Should `sell_price` be numeric.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
sell_price: 'not_numeric',
|
sell_price: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -345,10 +385,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `cost_price` be numeric.', async () => {
|
it('Should `cost_price` be numeric.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
cost_price: 'not_numeric',
|
cost_price: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -364,10 +405,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `sell_account_id` be integer.', async () => {
|
it('Should `sell_account_id` be integer.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
sell_account_id: 'not_numeric',
|
sell_account_id: 'not_numeric',
|
||||||
});
|
});
|
||||||
@@ -383,10 +425,11 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `cost_account_id` be integer.', async () => {
|
it('Should `cost_account_id` be integer.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
cost_account_id: 'not_numeric',
|
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 () => {
|
it ('Should response bad request in case cost account was not exist.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -422,17 +466,18 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response bad request in case sell account was not exist.', async () => {
|
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()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Item Name',
|
name: 'Item Name',
|
||||||
type: 'product',
|
type: 'product',
|
||||||
sell_price: 10.2,
|
sell_price: 10.2,
|
||||||
cost_price: 20.2,
|
cost_price: 20.2,
|
||||||
sell_account_id: 10,
|
sell_account_id: 1000000,
|
||||||
cost_account_id: 20,
|
cost_account_id: 1000000,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.status).equals(400);
|
expect(res.status).equals(400);
|
||||||
@@ -442,14 +487,15 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should update details of the given item.', async () => {
|
it('Should update details of the given item.', async () => {
|
||||||
const account = await create('account');
|
const account = await tenantFactory.create('account');
|
||||||
const anotherAccount = await create('account');
|
const anotherAccount = await tenantFactory.create('account');
|
||||||
const itemCategory = await create('item_category');
|
const itemCategory = await tenantFactory.create('item_category');
|
||||||
|
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/items/${item.id}`)
|
.post(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'New Item Name',
|
name: 'New Item Name',
|
||||||
type: 'service',
|
type: 'service',
|
||||||
@@ -460,7 +506,7 @@ describe('routes: `/items`', () => {
|
|||||||
category_id: itemCategory.id,
|
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.name).equals('New Item Name');
|
||||||
expect(updatedItem.type).equals('service');
|
expect(updatedItem.type).equals('service');
|
||||||
@@ -477,29 +523,32 @@ describe('routes: `/items`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/items/10')
|
.delete('/api/items/10')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success in case was exist.', async () => {
|
it('Should response success in case was exist.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete(`/api/items/${item.id}`)
|
.delete(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the given item from the storage.', async () => {
|
it('Should delete the given item from the storage.', async () => {
|
||||||
const item = await create('item');
|
const item = await tenantFactory.create('item');
|
||||||
await request()
|
await request()
|
||||||
.delete(`/api/items/${item.id}`)
|
.delete(`/api/items/${item.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.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);
|
expect(storedItems).to.have.lengthOf(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -511,31 +560,17 @@ describe('routes: `/items`', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
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 () => {
|
it('Should retrieve items list with associated accounts.', async () => {
|
||||||
await create('resource', { name: 'items' });
|
await tenantFactory.create('resource', { name: 'items' });
|
||||||
await create('item');
|
await tenantFactory.create('item');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/items')
|
.get('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
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 () => {
|
it('Should retrieve ordered items based on the given `column_sort_order` and `sort_order` query.', async () => {
|
||||||
await create('item', { name: 'ahmed' });
|
await tenantFactory.create('item', { name: 'ahmed' });
|
||||||
await create('item', { name: 'mohamed' });
|
await tenantFactory.create('item', { name: 'mohamed' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/items')
|
.get('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
column_sort_order: 'name',
|
column_sort_order: 'name',
|
||||||
sort_order: 'desc',
|
sort_order: 'desc',
|
||||||
@@ -569,11 +605,12 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve pagination meta of items list.', async () => {
|
it('Should retrieve pagination meta of items list.', async () => {
|
||||||
await create('resource', { name: 'items' });
|
await tenantFactory.create('resource', { name: 'items' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/items')
|
.get('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.items.results).to.be.a('array');
|
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 () => {
|
it('Should retrieve filtered items based on custom view conditions.', async () => {
|
||||||
const item1 = await create('item', { type: 'service' });
|
const item1 = await tenantFactory.create('item', { type: 'service' });
|
||||||
const item2 = await create('item', { type: 'service' });
|
const item2 = await tenantFactory.create('item', { type: 'service' });
|
||||||
const item3 = await create('item', { type: 'inventory' });
|
const item3 = await tenantFactory.create('item', { type: 'inventory' });
|
||||||
const item4 = await 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',
|
name: 'Items Inventory',
|
||||||
resource_id: 2,
|
resource_id: 2,
|
||||||
roles_logic_expression: '1',
|
roles_logic_expression: '1',
|
||||||
});
|
});
|
||||||
const viewCondition = await create('view_role', {
|
const viewCondition = await tenantFactory.create('view_role', {
|
||||||
view_id: view.id,
|
view_id: view.id,
|
||||||
index: 1,
|
index: 1,
|
||||||
field_id: 11,
|
field_id: 12,
|
||||||
value: 'inventory',
|
value: 'inventory',
|
||||||
comparator: 'equals',
|
comparator: 'equals',
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/items')
|
.get('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
custom_view_id: view.id,
|
custom_view_id: view.id,
|
||||||
})
|
})
|
||||||
@@ -618,14 +656,15 @@ describe('routes: `/items`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve filtered items based on filtering conditions.', async () => {
|
it('Should retrieve filtered items based on filtering conditions.', async () => {
|
||||||
const item1 = await create('item', { type: 'service' });
|
const item1 = await tenantFactory.create('item', { type: 'service' });
|
||||||
const item2 = await create('item', { type: 'service', name: 'target' });
|
const item2 = await tenantFactory.create('item', { type: 'service', name: 'target' });
|
||||||
const item3 = await create('item', { type: 'inventory' });
|
const item3 = await tenantFactory.create('item', { type: 'inventory' });
|
||||||
const item4 = await create('item', { type: 'inventory' });
|
const item4 = await tenantFactory.create('item', { type: 'inventory' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/items')
|
.get('/api/items')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
stringified_filter_roles: JSON.stringify([
|
stringified_filter_roles: JSON.stringify([
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,33 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
expect,
|
expect,
|
||||||
create,
|
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import knex from '@/database/knex';
|
import ItemCategory from '@/models/ItemCategory';
|
||||||
|
import {
|
||||||
let loginRes;
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
describe('routes: /item_categories/', () => {
|
describe('routes: /item_categories/', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('POST `/items_categories``', async () => {
|
describe('POST `/items_categories``', async () => {
|
||||||
it('Should not create a item category if the user was not authorized.', async () => {
|
it('Should not create a item category if the user was not authorized.', async () => {
|
||||||
const res = await request().post('/api/item_categories').send();
|
const res = await request().post('/api/item_categories').send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/item_categories')
|
.post('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -38,6 +33,7 @@ describe('routes: /item_categories/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/item_categories')
|
.post('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Clothes',
|
name: 'Clothes',
|
||||||
parent_category_id: 10,
|
parent_category_id: 10,
|
||||||
@@ -53,6 +49,7 @@ describe('routes: /item_categories/', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/item_categories')
|
.post('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Clothes',
|
name: 'Clothes',
|
||||||
description: 'Here is description',
|
description: 'Here is description',
|
||||||
@@ -66,10 +63,11 @@ describe('routes: /item_categories/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should item category data be saved to the storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.post('/api/item_categories')
|
.post('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Clothes',
|
name: 'Clothes',
|
||||||
description: 'Here is description',
|
description: 'Here is description',
|
||||||
@@ -78,8 +76,9 @@ describe('routes: /item_categories/', () => {
|
|||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
|
|
||||||
const storedCategory = await knex('items_categories')
|
const storedCategory = await ItemCategory.tenant().query()
|
||||||
.where('id', res.body.category.id).first();
|
.where('id', res.body.category.id)
|
||||||
|
.first();
|
||||||
|
|
||||||
expect(storedCategory.name).equals('Clothes');
|
expect(storedCategory.name).equals('Clothes');
|
||||||
expect(storedCategory.description).equals('Here is description');
|
expect(storedCategory.description).equals('Here is description');
|
||||||
@@ -90,32 +89,33 @@ describe('routes: /item_categories/', () => {
|
|||||||
|
|
||||||
describe('POST `/items_category/{id}`', () => {
|
describe('POST `/items_category/{id}`', () => {
|
||||||
it('Should not update a item category if the user was not authorized.', async () => {
|
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()
|
const res = await request()
|
||||||
.post(`/api/item_categories/${category.id}`)
|
.post(`/api/item_categories/${category.id}`)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const category = await create('item_category');
|
const category = await tenantFactory.create('item_category');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/item_categories/${category.id}`)
|
.post(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
.send({
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
name: '',
|
.send();
|
||||||
});
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `parent_category_id` be exist in the storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.post(`/api/item_categories/${category.id}`)
|
.post(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
parent_category_id: 10,
|
parent_category_id: 10,
|
||||||
@@ -128,12 +128,13 @@ describe('routes: /item_categories/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success with correct data format.', async () => {
|
it('Should response success with correct data format.', async () => {
|
||||||
const category = await create('item_category');
|
const category = await tenantFactory.create('item_category');
|
||||||
const anotherCategory = await create('item_category');
|
const anotherCategory = await tenantFactory.create('item_category');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/item_categories/${category.id}`)
|
.post(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
parent_category_id: anotherCategory.id,
|
parent_category_id: anotherCategory.id,
|
||||||
@@ -144,20 +145,22 @@ describe('routes: /item_categories/', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should item category data be update in the storage.', async () => {
|
it('Should item category data be update in the storage.', async () => {
|
||||||
const category = await create('item_category');
|
const category = await tenantFactory.create('item_category');
|
||||||
const anotherCategory = await create('item_category');
|
const anotherCategory = await tenantFactory.create('item_category');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/item_categories/${category.id}`)
|
.post(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
parent_category_id: anotherCategory.id,
|
parent_category_id: anotherCategory.id,
|
||||||
description: 'updated description',
|
description: 'updated description',
|
||||||
});
|
});
|
||||||
|
|
||||||
const storedCategory = await knex('items_categories')
|
const storedCategory = await ItemCategory.tenant().query()
|
||||||
.where('id', res.body.id).first();
|
.where('id', res.body.id)
|
||||||
|
.first();
|
||||||
|
|
||||||
expect(storedCategory.name).equals('Name');
|
expect(storedCategory.name).equals('Name');
|
||||||
expect(storedCategory.description).equals('updated description');
|
expect(storedCategory.description).equals('updated description');
|
||||||
@@ -167,43 +170,48 @@ describe('routes: /item_categories/', () => {
|
|||||||
|
|
||||||
describe('DELETE: `/items_categories`', async () => {
|
describe('DELETE: `/items_categories`', async () => {
|
||||||
it('Should not delete the give item category if the user was not authorized.', 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()
|
const res = await request()
|
||||||
.delete(`/api/item_categories/${category.id}`)
|
.delete(`/api/item_categories/${category.id}`)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should not delete if the item category was not found.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/item_categories/10')
|
.delete('/api/item_categories/10')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success after delete the given item category.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/item_categories/${category.id}`)
|
.delete(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the give item category from the storage.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/item_categories/${category.id}`)
|
.delete(`/api/item_categories/${category.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.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);
|
expect(categories).to.have.lengthOf(0);
|
||||||
});
|
});
|
||||||
@@ -212,12 +220,13 @@ describe('routes: /item_categories/', () => {
|
|||||||
describe('GET: `/item_categories`', () => {
|
describe('GET: `/item_categories`', () => {
|
||||||
|
|
||||||
it('Should retrieve list of item categories.', async () => {
|
it('Should retrieve list of item categories.', async () => {
|
||||||
const category1 = await create('item_category');
|
const category1 = await tenantFactory.create('item_category');
|
||||||
const category2 = await create('item_category', { parent_category_id: category1.id });
|
const category2 = await tenantFactory.create('item_category', { parent_category_id: category1.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/item_categories')
|
.get('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.categories).to.be.a('array');
|
expect(res.body.categories).to.be.a('array');
|
||||||
@@ -233,14 +242,15 @@ describe('routes: /item_categories/', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('Should retrieve of related items.', async () => {
|
it('Should retrieve of related items.', async () => {
|
||||||
const category1 = await create('item_category');
|
const category1 = await tenantFactory.create('item_category');
|
||||||
const category2 = await create('item_category', { parent_category_id: category1.id });
|
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()
|
const res = await request()
|
||||||
.get('/api/item_categories')
|
.get('/api/item_categories')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.categories[0].count).to.be.a('number');
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
import knex from '@/database/knex';
|
|
||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
expect,
|
expect,
|
||||||
create,
|
|
||||||
make,
|
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import Option from '@/models/Option';
|
import Option from '@/models/Option';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: `/options`', () => {
|
describe('routes: `/options`', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('POST: `/options/`', () => {
|
describe('POST: `/options/`', () => {
|
||||||
it('Should response unauthorized if the user was not logged in.', async () => {
|
it('Should response unauthorized if the user was not logged in.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
@@ -25,13 +18,14 @@ describe('routes: `/options`', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should response the options key and group is not defined.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/options')
|
.post('/api/options')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
@@ -56,6 +50,7 @@ describe('routes: `/options`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/options')
|
.post('/api/options')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
options: [{
|
options: [{
|
||||||
key: 'name',
|
key: 'name',
|
||||||
@@ -65,7 +60,7 @@ describe('routes: `/options`', () => {
|
|||||||
});
|
});
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
|
|
||||||
const storedOptions = await Option.query()
|
const storedOptions = await Option.tenant().query()
|
||||||
.where('group', 'organization')
|
.where('group', 'organization')
|
||||||
.where('key', 'name');
|
.where('key', 'name');
|
||||||
|
|
||||||
@@ -83,16 +78,17 @@ describe('routes: `/options`', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should retrieve options the associated to the given group.', async () => {
|
||||||
await create('option', { group: 'organization', key: 'name' });
|
await tenantFactory.create('option', { group: 'organization', key: 'name' });
|
||||||
await create('option', { group: 'organization', key: 'base_currency' });
|
await tenantFactory.create('option', { group: 'organization', key: 'base_currency' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/options')
|
.get('/api/options')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
group: 'organization',
|
group: 'organization',
|
||||||
})
|
})
|
||||||
@@ -104,12 +100,13 @@ describe('routes: `/options`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve options that associated to the given key.', async () => {
|
it('Should retrieve options that associated to the given key.', async () => {
|
||||||
await create('option', { group: 'organization', key: 'base_currency' });
|
await tenantFactory.create('option', { group: 'organization', key: 'base_currency' });
|
||||||
await create('option', { group: 'organization', key: 'name' });
|
await tenantFactory.create('option', { group: 'organization', key: 'name' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/options')
|
.get('/api/options')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({
|
.query({
|
||||||
key: 'name',
|
key: 'name',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,35 +2,30 @@ import knex from '@/database/knex';
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
expect,
|
expect,
|
||||||
create,
|
|
||||||
make,
|
|
||||||
login,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: `/routes`', () => {
|
describe('routes: `/routes`', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('GET: `/users`', () => {
|
describe('GET: `/users`', () => {
|
||||||
it('Should response unauthorized if the user was not authorized.', async () => {
|
it('Should response unauthorized if the user was not authorized.', async () => {
|
||||||
const res = await request().get('/api/users');
|
const res = await request().get('/api/users');
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should retrieve the stored users with pagination meta.', async () => {
|
||||||
await create('user');
|
await tenantFactory.create('user');
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/users')
|
.get('/api/users')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.users.results.length).equals(2);
|
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`', () => {
|
describe('POST: `/users/:id`', () => {
|
||||||
it('Should create a new user if the user was not authorized.', async () => {
|
it('Should create a new user if the user was not authorized.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
const res = await request().post(`/api/users/${user.id}`);
|
const res = await request()
|
||||||
|
.post(`/api/users/${user.id}`);
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `first_name` be required.', async () => {
|
it('Should `first_name` be required.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/users/${user.id}`)
|
.post(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -246,10 +58,11 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `last_name` be required.', async () => {
|
it('Should `last_name` be required.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/users/${user.id}`)
|
.post(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -259,10 +72,11 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `email` be required.', async () => {
|
it('Should `email` be required.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/users/${user.id}`)
|
.post(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -272,10 +86,11 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should be `email` be valid format.', async () => {
|
it('Should be `email` be valid format.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/users/${user.id}`)
|
.post(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
first_name: user.first_name,
|
first_name: user.first_name,
|
||||||
last_name: user.last_name,
|
last_name: user.last_name,
|
||||||
@@ -291,10 +106,11 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `phone_number` be valid format.', async () => {
|
it('Should `phone_number` be valid format.', async () => {
|
||||||
const user = create('user');
|
const user = tenantFactory.create('user');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/users/${user.id}`)
|
.post(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
first_name: user.first_name,
|
first_name: user.first_name,
|
||||||
last_name: user.last_name,
|
last_name: user.last_name,
|
||||||
@@ -308,70 +124,32 @@ describe('routes: `/routes`', () => {
|
|||||||
const phoneNumberParam = res.body.errors.find((error) => error.param === 'phone_number');
|
const phoneNumberParam = res.body.errors.find((error) => error.param === 'phone_number');
|
||||||
expect(!!phoneNumberParam).equals(true);
|
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`', () => {
|
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 () => {
|
it('Should response not found if the user was not exist.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/users/10')
|
.get('/api/users/10')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success if the user was exist.', async () => {
|
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()
|
const res = await request()
|
||||||
.get(`/api/users/${user.id}`)
|
.get(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
@@ -379,14 +157,18 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('DELETE: `/users/:id`', () => {
|
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 () => {
|
it('Should response not found if the user was not exist.', async () => {
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/users/10')
|
.delete('/api/users/10')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
@@ -396,20 +178,22 @@ describe('routes: `/routes`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response success if the user was exist.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/users/${user.id}`)
|
.delete(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the give user from the storage.', async () => {
|
it('Should delete the give user from the storage.', async () => {
|
||||||
const user = await create('user');
|
const user = await tenantFactory.create('user');
|
||||||
await request()
|
await request()
|
||||||
.delete(`/api/users/${user.id}`)
|
.delete(`/api/users/${user.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
const storedUsers = await knex('users').where('id', user.id);
|
const storedUsers = await knex('users').where('id', user.id);
|
||||||
|
|||||||
@@ -1,35 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
request,
|
request,
|
||||||
expect,
|
expect,
|
||||||
login,
|
|
||||||
create,
|
|
||||||
} from '~/testInit';
|
} from '~/testInit';
|
||||||
import View from '@/models/View';
|
import View from '@/models/View';
|
||||||
import ViewRole from '@/models/ViewRole';
|
import ViewRole from '@/models/ViewRole';
|
||||||
import '@/models/ResourceField';
|
import '@/models/ResourceField';
|
||||||
import ViewColumn from '../../src/models/ViewColumn';
|
import ViewColumn from '../../src/models/ViewColumn';
|
||||||
|
import {
|
||||||
|
tenantWebsite,
|
||||||
|
tenantFactory,
|
||||||
|
loginRes
|
||||||
|
} from '~/dbInit';
|
||||||
|
|
||||||
let loginRes;
|
|
||||||
|
|
||||||
describe('routes: `/views`', () => {
|
describe('routes: `/views`', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
loginRes = await login();
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
loginRes = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('GET: `/views`', () => {
|
describe('GET: `/views`', () => {
|
||||||
it('Should response unauthorized in case the user was not authorized.', async () => {
|
it('Should response unauthorized in case the user was not authorized.', async () => {
|
||||||
const res = await request().get('/api/views');
|
const res = await request().get('/api/views');
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should retrieve all views of the given resource name.', async () => {
|
||||||
const resource = await create('resource', { name: 'resource_name' });
|
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
|
||||||
const resourceFields = await create('view', {
|
const resourceFields = await tenantFactory.create('view', {
|
||||||
name: 'Resource View',
|
name: 'Resource View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '',
|
roles_logic_expression: '',
|
||||||
@@ -38,6 +33,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/views')
|
.get('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.query({ resource_name: 'resource_name' })
|
.query({ resource_name: 'resource_name' })
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
@@ -48,8 +44,8 @@ describe('routes: `/views`', () => {
|
|||||||
|
|
||||||
describe('GET `/views/:id`', () => {
|
describe('GET `/views/:id`', () => {
|
||||||
it('Should response unauthorized in case the user was not authorized.', async () => {
|
it('Should response unauthorized in case the user was not authorized.', async () => {
|
||||||
const resource = await create('resource', { name: 'resource_name' });
|
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
|
||||||
const resourceView = await create('view', {
|
const resourceView = await tenantFactory.create('view', {
|
||||||
name: 'Resource View',
|
name: 'Resource View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '',
|
roles_logic_expression: '',
|
||||||
@@ -61,12 +57,12 @@ describe('routes: `/views`', () => {
|
|||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
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 () => {
|
it('Should response not found in case the given view was not found.', async () => {
|
||||||
const resource = await create('resource', { name: 'resource_name' });
|
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
|
||||||
const resourceView = await create('view', {
|
const resourceView = await tenantFactory.create('view', {
|
||||||
name: 'Resource View',
|
name: 'Resource View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '',
|
roles_logic_expression: '',
|
||||||
@@ -75,6 +71,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get('/api/views/123')
|
.get('/api/views/123')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
expect(res.status).equals(404);
|
||||||
@@ -84,13 +81,13 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should retrieve details of the given view with associated graphs.', async () => {
|
it('Should retrieve details of the given view with associated graphs.', async () => {
|
||||||
const resource = await create('resource', { name: 'resource_name' });
|
const resource = await tenantFactory.create('resource', { name: 'resource_name' });
|
||||||
const resourceView = await create('view', {
|
const resourceView = await tenantFactory.create('view', {
|
||||||
name: 'Resource View',
|
name: 'Resource View',
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
roles_logic_expression: '1 AND 2',
|
roles_logic_expression: '1 AND 2',
|
||||||
});
|
});
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
label_name: 'Expense Account',
|
label_name: 'Expense Account',
|
||||||
key: 'expense_account',
|
key: 'expense_account',
|
||||||
data_type: 'integer',
|
data_type: 'integer',
|
||||||
@@ -99,7 +96,7 @@ describe('routes: `/views`', () => {
|
|||||||
predefined: true,
|
predefined: true,
|
||||||
builtin: true,
|
builtin: true,
|
||||||
});
|
});
|
||||||
const viewRole = await create('view_role', {
|
const viewRole = await tenantFactory.create('view_role', {
|
||||||
view_id: resourceView.id,
|
view_id: resourceView.id,
|
||||||
index: 1,
|
index: 1,
|
||||||
field_id: resourceField.id,
|
field_id: resourceField.id,
|
||||||
@@ -110,6 +107,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.get(`/api/views/${resourceView.id}`)
|
.get(`/api/views/${resourceView.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(200);
|
expect(res.status).equals(200);
|
||||||
@@ -127,14 +125,15 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request().post('/api/views');
|
const res = await request().post('/api/views');
|
||||||
|
|
||||||
expect(res.status).equals(401);
|
expect(res.status).equals(401);
|
||||||
expect(res.body.message).equals('unauthorized');
|
expect(res.body.message).equals('Unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
await create('resource');
|
await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.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.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
@@ -144,10 +143,11 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `resource_name` be required.', async () => {
|
it('Should `resource_name` be required.', async () => {
|
||||||
await create('resource');
|
await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.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.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
@@ -157,13 +157,14 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `columns` be minimum limited', async () => {
|
it('Should `columns` be minimum limited', async () => {
|
||||||
await create('resource');
|
await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views', {
|
.post('/api/views', {
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
columns: [],
|
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.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
@@ -173,13 +174,14 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `columns` be array.', async () => {
|
it('Should `columns` be array.', async () => {
|
||||||
await create('resource');
|
await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views', {
|
.post('/api/views', {
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
columns: 'not_array',
|
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.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
@@ -189,10 +191,11 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `roles.*.field_key` be required.', async () => {
|
it('Should `roles.*.field_key` be required.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
@@ -207,10 +210,11 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `roles.*.comparator` be valid.', async () => {
|
it('Should `roles.*.comparator` be valid.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
@@ -225,7 +229,7 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `roles.*.index` be number as integer.', async () => {
|
it('Should `roles.*.index` be number as integer.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.send({
|
.send({
|
||||||
@@ -235,7 +239,8 @@ describe('routes: `/views`', () => {
|
|||||||
{ index: 'not_numeric' },
|
{ 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.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
@@ -251,6 +256,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: 'not_found',
|
resource_name: 'not_found',
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
@@ -275,8 +281,8 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should response invalid logic expression.', async () =>{
|
it('Should response invalid logic expression.', async () =>{
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
await create('resource_field', {
|
await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
@@ -284,6 +290,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
logic_expression: '100 && 100',
|
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 () => {
|
it('Should response the roles fields not exist in case role field was not exist.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
await create('resource_field', { resource_id: resource.id, label_name: 'Amount' });
|
await tenantFactory.create('resource_field', { resource_id: resource.id, label_name: 'Amount' });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
name: 'View Label',
|
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 () => {
|
it('Should response the columns that not exists in case column was not exist.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
@@ -343,6 +351,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
@@ -366,8 +375,8 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should save the given details of the view.', async () => {
|
it('Should save the given details of the view.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
await create('resource_field', {
|
await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
@@ -375,6 +384,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
name: 'View Label',
|
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.name).equals('View Label');
|
||||||
expect(storedView.predefined).equals(0);
|
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 () => {
|
it('Should save the given details of view fields that associated to the given view id.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
@@ -408,6 +418,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
name: 'View Label',
|
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.length).equals(1);
|
||||||
expect(viewRoles[0].index).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 () => {
|
it('Should save columns that associated to the given view.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
@@ -441,6 +452,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.post('/api/views')
|
.post('/api/views')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
resource_name: resource.name,
|
resource_name: resource.name,
|
||||||
name: 'View Label',
|
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);
|
expect(viewColumns.length).equals(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -465,10 +477,11 @@ describe('routes: `/views`', () => {
|
|||||||
|
|
||||||
describe('POST: `/views/:view_id`', () => {
|
describe('POST: `/views/:view_id`', () => {
|
||||||
it('Should `name` be required.', async () => {
|
it('Should `name` be required.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -479,13 +492,14 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should columns be minimum limited', async () => {
|
it('Should columns be minimum limited', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`, {
|
.post(`/api/views/${view.id}`, {
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
columns: [],
|
columns: [],
|
||||||
})
|
})
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
@@ -496,27 +510,31 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should columns be array.', async () => {
|
it('Should columns be array.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`, {
|
.post(`/api/views/${view.id}`, {
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
columns: 'not_array',
|
columns: 'not_array',
|
||||||
})
|
})
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
.send();
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
|
.send({
|
||||||
|
columns: 'columns'
|
||||||
|
});
|
||||||
|
|
||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
expect(res.body.errors).include.something.deep.equals({
|
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 () => {
|
it('Should `roles.*.field_key` be required.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
roles: [{}],
|
roles: [{}],
|
||||||
@@ -525,15 +543,16 @@ describe('routes: `/views`', () => {
|
|||||||
expect(res.status).equals(422);
|
expect(res.status).equals(422);
|
||||||
expect(res.body.code).equals('validation_error');
|
expect(res.body.code).equals('validation_error');
|
||||||
expect(res.body.errors).include.something.deep.equals({
|
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 () => {
|
it('Should `roles.*.comparator` be required.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
roles: [{}],
|
roles: [{}],
|
||||||
@@ -547,10 +566,11 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should `roles.*.index` be number as integer.', async () => {
|
it('Should `roles.*.index` be number as integer.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
label: 'View Label',
|
label: 'View Label',
|
||||||
roles: [{ index: 'not_numeric' }],
|
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 () => {
|
it('Should response the roles fields not exist in case role field was not exist.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
await create('resource_field', {
|
await tenantFactory.create('resource_field', {
|
||||||
resource_id: view.resource_id,
|
resource_id: view.resource_id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
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 () => {
|
it('Should response the resource columns not exists in case the column keys was not exist.', async () => {
|
||||||
const view = await create('view');
|
const view = await tenantFactory.create('view');
|
||||||
await create('resource_field', {
|
await tenantFactory.create('resource_field', {
|
||||||
resource_id: view.resource_id,
|
resource_id: view.resource_id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
logic_expression: '1',
|
||||||
@@ -641,21 +663,22 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete the view roles that not presented the post data.', async () => {
|
it('Should delete the view roles that not presented the post data.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
});
|
});
|
||||||
|
|
||||||
const view = await create('view', { resource_id: resource.id });
|
const view = await tenantFactory.create('view', { resource_id: resource.id });
|
||||||
const viewRole = await create('view_role', {
|
const viewRole = await tenantFactory.create('view_role', {
|
||||||
view_id: view.id,
|
view_id: view.id,
|
||||||
field_id: resourceField.id,
|
field_id: resourceField.id,
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
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);
|
expect(foundViewRole.length).equals(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should update the view roles that presented in the given data.', async () => {
|
it('Should update the view roles that presented in the given data.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
});
|
});
|
||||||
|
|
||||||
const view = await create('view', { resource_id: resource.id });
|
const view = await tenantFactory.create('view', { resource_id: resource.id });
|
||||||
const viewRole = await create('view_role', {
|
const viewRole = await tenantFactory.create('view_role', {
|
||||||
view_id: view.id,
|
view_id: view.id,
|
||||||
field_id: resourceField.id,
|
field_id: resourceField.id,
|
||||||
});
|
});
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
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.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].index).equals(1);
|
||||||
expect(foundViewRole[0].value).equals('100');
|
expect(foundViewRole[0].value).equals('100');
|
||||||
expect(foundViewRole[0].comparator).equals('equals');
|
expect(foundViewRole[0].comparator).equals('equals');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should response not found roles ids in case not exists in the storage.', async () => {
|
it('Should response not found roles ids in case not exists in the storage.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: '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()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
logic_expression: '1',
|
||||||
@@ -750,18 +775,19 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should delete columns from storage in case view columns ids not presented.', async () => {
|
it('Should delete columns from storage in case view columns ids not presented.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
});
|
});
|
||||||
const view = await create('view', { resource_id: resource.id });
|
const view = await tenantFactory.create('view', { resource_id: resource.id });
|
||||||
const viewColumn = await create('view_column', { view_id: view.id });
|
const viewColumn = await tenantFactory.create('view_column', { view_id: view.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
logic_expression: '1',
|
||||||
@@ -778,22 +804,23 @@ describe('routes: `/views`', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// console.log(res.status, res.body);
|
// 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);
|
expect(foundViewColumns.length).equals(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should insert columns to the storage if where new columns', async () => {
|
it('Should insert columns to the storage if where new columns', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: '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()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
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.length).equals(1);
|
||||||
expect(foundViewColumns[0].viewId).equals(view.id);
|
expect(foundViewColumns[0].viewId).equals(view.id);
|
||||||
@@ -819,18 +846,19 @@ describe('routes: `/views`', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('Should update columns on the storage.', async () => {
|
it('Should update columns on the storage.', async () => {
|
||||||
const resource = await create('resource');
|
const resource = await tenantFactory.create('resource');
|
||||||
const resourceField = await create('resource_field', {
|
const resourceField = await tenantFactory.create('resource_field', {
|
||||||
resource_id: resource.id,
|
resource_id: resource.id,
|
||||||
label_name: 'Amount',
|
label_name: 'Amount',
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
});
|
});
|
||||||
const view = await create('view', { resource_id: resource.id });
|
const view = await tenantFactory.create('view', { resource_id: resource.id });
|
||||||
const viewColumn = await create('view_column', { view_id: view.id });
|
const viewColumn = await tenantFactory.create('view_column', { view_id: view.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.post(`/api/views/${view.id}`)
|
.post(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send({
|
.send({
|
||||||
name: 'View Label',
|
name: 'View Label',
|
||||||
logic_expression: '1',
|
logic_expression: '1',
|
||||||
@@ -849,7 +877,7 @@ describe('routes: `/views`', () => {
|
|||||||
|
|
||||||
console.log(res.body)
|
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.length).equals(1);
|
||||||
expect(foundViewColumns[0].id).equals(viewColumn.id);
|
expect(foundViewColumns[0].id).equals(viewColumn.id);
|
||||||
@@ -861,10 +889,11 @@ describe('routes: `/views`', () => {
|
|||||||
|
|
||||||
describe('DELETE: `/views/:resource_id`', () => {
|
describe('DELETE: `/views/:resource_id`', () => {
|
||||||
it('Should not delete predefined view.', async () => {
|
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()
|
const res = await request()
|
||||||
.delete(`/api/views/${view.id}`)
|
.delete(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(400);
|
expect(res.status).equals(400);
|
||||||
@@ -877,6 +906,7 @@ describe('routes: `/views`', () => {
|
|||||||
const res = await request()
|
const res = await request()
|
||||||
.delete('/api/views/100')
|
.delete('/api/views/100')
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).equals(404);
|
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 () => {
|
it('Should delete the given view and associated view columns and roles.', async () => {
|
||||||
const view = await create('view', { predefined: false });
|
const view = await tenantFactory.create('view', { predefined: false });
|
||||||
await create('view_role', { view_id: view.id });
|
await tenantFactory.create('view_role', { view_id: view.id });
|
||||||
await create('view_column', { view_id: view.id });
|
await tenantFactory.create('view_column', { view_id: view.id });
|
||||||
|
|
||||||
const res = await request()
|
const res = await request()
|
||||||
.delete(`/api/views/${view.id}`)
|
.delete(`/api/views/${view.id}`)
|
||||||
.set('x-access-token', loginRes.body.token)
|
.set('x-access-token', loginRes.body.token)
|
||||||
|
.set('organization-id', tenantWebsite.organizationId)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.body.id).equals(view.id);
|
expect(res.body.id).equals(view.id);
|
||||||
|
|
||||||
const foundViews = await View.query().where('id', view.id);
|
const foundViews = await View.tenant().query().where('id', view.id);
|
||||||
const foundViewRoles = await ViewRole.query().where('view_id', view.id);
|
const foundViewRoles = await ViewRole.tenant().query().where('view_id', view.id);
|
||||||
|
|
||||||
expect(foundViews).to.have.lengthOf(0);
|
expect(foundViews).to.have.lengthOf(0);
|
||||||
expect(foundViewRoles).to.have.lengthOf(0);
|
expect(foundViewRoles).to.have.lengthOf(0);
|
||||||
|
|||||||
@@ -1,54 +1,88 @@
|
|||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
import chaiHttp from 'chai-http';
|
import chaiHttp from 'chai-http';
|
||||||
import chaiThings from 'chai-things';
|
import chaiThings from 'chai-things';
|
||||||
|
import systemDb from '@/database/knex';
|
||||||
import knex from '@/database/knex';
|
|
||||||
import '@/models';
|
|
||||||
import app from '@/app';
|
import app from '@/app';
|
||||||
import factory from '@/database/factories';
|
import createTenantFactory from '@/database/factories';
|
||||||
import dbManager from '@/database/manager';
|
import TenantsManager from '@/system/TenantsManager';
|
||||||
// import { hashPassword } from '@/utils';
|
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 { expect } = chai;
|
||||||
|
const request = () => chai.request(app);
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await knex.migrate.rollback();
|
// Rollback/migrate the system database.
|
||||||
await knex.migrate.latest();
|
await systemDb.migrate.rollback();
|
||||||
|
await systemDb.migrate.latest();
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
afterEach(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
chai.use(chaiHttp);
|
chai.use(chaiHttp);
|
||||||
chai.use(chaiThings);
|
chai.use(chaiThings);
|
||||||
|
|
||||||
const create = async (name, data) => factory.create(name, data);
|
// Create tenant database.
|
||||||
const make = async (name, data) => factory.build(name, data);
|
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 {
|
export {
|
||||||
login,
|
login,
|
||||||
create,
|
systemFactory,
|
||||||
make,
|
createTenantFactory,
|
||||||
|
createTenant,
|
||||||
|
createUser,
|
||||||
|
dropTenant,
|
||||||
expect,
|
expect,
|
||||||
request,
|
request,
|
||||||
|
bindTenantModel,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user