UNPKG

adminjs

Version:
279 lines 9.36 kB
import chai, { expect } from 'chai'; import chaiChange from 'chai-change'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import BaseRecord from './base-record.js'; import BaseResource from '../resource/base-resource.js'; import BaseProperty from '../property/base-property.js'; import ValidationError from '../../utils/errors/validation-error.js'; import { ResourceDecorator } from '../../decorators/index.js'; chai.use(chaiAsPromised); chai.use(chaiChange); chai.use(sinonChai); describe('Record', function () { let record; let params = { param1: 'john' }; afterEach(function () { sinon.restore(); }); describe('#get', function () { context('record with nested parameters', function () { const nested3level = 'value'; beforeEach(function () { params = { nested1level: { nested2level: { nested3level } } }; record = new BaseRecord(params, {}); }); it('returns deepest field when all up-level keys are given', function () { expect(record.get('nested1level.nested2level.nested3level')).to.equal(nested3level); }); it('returns object when all up-level keys are given except one', function () { expect(record.get('nested1level.nested2level')).to.deep.equal({ nested3level }); }); it('returns object when only first level key is given', function () { expect(record.get('nested1level')).to.deep.equal({ nested2level: { nested3level } }); }); it('returns undefined when passing unknown param', function () { expect(record.get('nested1level.nested2')).to.be.undefined; }); }); }); describe('#constructor', function () { it('returns empty object if params are not passed to the constructor', function () { record = new BaseRecord({}, {}); expect(record.params).to.deep.equal({}); }); it('stores flatten object params', function () { record = new BaseRecord({ auth: { login: 'login' } }, {}); expect(record.params).to.deep.equal({ 'auth.login': 'login' }); }); }); describe('#save', function () { const newParams = { param2: 'doe' }; const properties = [new BaseProperty({ path: '_id', isId: true })]; let resource; beforeEach(function () { resource = sinon.createStubInstance(BaseResource, { properties: sinon.stub().returns(properties), create: sinon.stub().resolves(newParams), update: sinon.stub().resolves(newParams) }); }); it('uses BaseResource#create method when there is no id property', async function () { record = new BaseRecord(newParams, resource); record.save(); expect(resource.create).to.have.been.calledWith(newParams); }); it('uses BaseResource#update method when there is a id property', function () { const _id = '1231231313'; record = new BaseRecord({ ...newParams, _id }, resource); record.save(); expect(resource.update).to.have.been.calledWith(_id, { ...newParams, _id }); }); it('stores validation error when they happen', async function () { const baseError = { message: 'test base error' }; const propertyErrors = { param2: { type: 'required', message: 'Field is required' } }; resource.create = sinon.stub().rejects(new ValidationError(propertyErrors, baseError)); record = new BaseRecord(newParams, resource); await record.save(); expect(record.error('param2')).to.deep.equal(propertyErrors.param2); expect(record.baseError).to.deep.equal(baseError); }); it('stores validation error when they happen (even when there is no baseError specified)', async function () { const propertyErrors = { param2: { type: 'required', message: 'Field is required' } }; resource.create = sinon.stub().rejects(new ValidationError(propertyErrors)); record = new BaseRecord(newParams, resource); await record.save(); expect(record.error('param2')).to.deep.equal(propertyErrors.param2); expect(record.baseError).to.be.null; }); }); describe('#update', function () { const newParams = { param2: 'doe' }; const properties = [new BaseProperty({ path: '_id', isId: true })]; params = { param1: 'john', _id: '1381723981273' }; let resource; context('resource stores the value', function () { beforeEach(async function () { resource = sinon.createStubInstance(BaseResource, { properties: sinon.stub().returns(properties), update: sinon.stub().resolves(newParams) }); record = new BaseRecord(params, resource); await record.update(newParams); }); it('stores what was returned by BaseResource#update to this.params', function () { expect(record.get('param2')).to.equal(newParams.param2); }); it('resets the baseError when there is none', function () { expect(record.baseError).to.deep.equal(null); }); it('resets the errors when there are none', function () { expect(record.errors).to.deep.equal({}); }); it('calls the BaseResource#update function with the id and new params', function () { expect(resource.update).to.have.been.calledWith(params._id, newParams); }); }); context('resource throws validation error', function () { const baseError = { message: 'test base error' }; const propertyErrors = { param2: { type: 'required', message: 'Field is required' } }; beforeEach(async function () { resource = sinon.createStubInstance(BaseResource, { properties: sinon.stub().returns(properties), update: sinon.stub().rejects(new ValidationError(propertyErrors, baseError)) }); record = new BaseRecord(params, resource); this.returnedValue = await record.update(newParams); }); it('stores validation baseError', function () { expect(record.baseError).to.deep.equal(baseError); }); it('stores validation errors', function () { expect(record.error('param2')).to.deep.equal(propertyErrors.param2); }); it('returns itself', function () { expect(this.returnedValue).to.equal(record); }); }); }); describe('#isValid', function () { it('returns true when there are no errors', function () { record.errors = {}; expect(record.isValid()).to.equal(true); }); it('returns false when there is at least on error', function () { record.errors = { pathWithError: { type: 'required', message: 'I am error' } }; expect(record.isValid()).to.equal(false); }); }); describe('#title', function () { const properties = [new BaseProperty({ path: 'name' })]; params = { name: 'john', _id: '1381723981273' }; it('returns value in title property', function () { const resource = sinon.createStubInstance(BaseResource, { properties: sinon.stub().returns(properties) }); record = new BaseRecord(params, resource); expect(record.title()).to.equal(params.name); }); }); describe('#populate', function () { it('sets populated field', function () { const populated = { value: new BaseRecord({}, {}) }; record = new BaseRecord(params, {}); record.populate('value', populated.value); expect(record.populated.value).to.equal(populated.value); }); it('clears populated field when record is null or undefined', () => { record = new BaseRecord(params, {}); record.populate('value', 'something'); expect(() => { record.populate('value', null); }).to.alter(() => record.populated.value, { from: 'something', to: undefined }); }); }); describe('#toJSON', () => { const param = 'populatedProperty'; let resource; beforeEach(() => { resource = sinon.createStubInstance(BaseResource, { properties: sinon.stub().returns([]), decorate: sinon.stub().returns(sinon.createStubInstance(ResourceDecorator, { recordActions: sinon.stub().returns([]), bulkActions: sinon.stub().returns([]) })) }); record = new BaseRecord(params, resource); }); it('changes populated records to JSON', () => { const refRecord = sinon.createStubInstance(BaseRecord, { toJSON: sinon.stub() }); record.populate(param, refRecord); sinon.stub(record, 'id').returns('1'); record.toJSON(); expect(refRecord.toJSON).to.have.been.calledOnce; }); it('does not changes to JSON when in populated there is something else than BaseRecord', () => { record.populate(param, 'something else'); sinon.stub(record, 'id').returns('1'); expect(() => { record.toJSON(); }).not.to.throw(); }); }); });