adminjs
Version:
Admin panel for apps written in node.js
184 lines • 6.6 kB
JavaScript
import { expect } from 'chai';
import sinon from 'sinon';
import PropertyDecorator from './property-decorator.js';
import BaseProperty from '../../adapters/property/base-property.js';
import AdminJS from '../../../adminjs.js';
describe('PropertyDecorator', () => {
const normalName = 'normalName';
let stubbedAdmin;
let property;
let args;
beforeEach(() => {
property = new BaseProperty({
path: 'name',
type: 'string'
});
stubbedAdmin = sinon.createStubInstance(AdminJS);
// stubbedAdmin.translateProperty = sinon.stub().returns(normalName) as any
args = {
property,
admin: stubbedAdmin,
resource: {
id: () => 'someId'
}
};
});
describe('#isSortable', () => {
it('passes the execution to the base property', () => {
sinon.stub(BaseProperty.prototype, 'isSortable').returns(false);
expect(new PropertyDecorator(args).isSortable()).to.equal(false);
});
});
describe('#isVisible', () => {
it('passes execution to BaseProperty.isVisible for list when no options are specified', () => {
expect(new PropertyDecorator(args).isVisible('list')).to.equal(property.isVisible());
});
it('passes execution to BaseProperty.isEditable for edit when no options are specified', () => {
sinon.stub(BaseProperty.prototype, 'isVisible').returns(false);
expect(new PropertyDecorator(args).isVisible('edit')).to.equal(property.isEditable());
});
it('sets new value when it is changed for all views by isVisible option', () => {
const decorator = new PropertyDecorator({
...args,
options: {
isVisible: false
}
});
expect(decorator.isVisible('list')).to.equal(false);
expect(decorator.isVisible('edit')).to.equal(false);
expect(decorator.isVisible('show')).to.equal(false);
});
});
describe('#label', () => {
it('returns translated label', () => {
sinon.stub(BaseProperty.prototype, 'name').returns('normalName');
expect(new PropertyDecorator(args).label()).to.equal(normalName);
});
});
describe('#reference', () => {
const rawReferenceValue = 'Article';
const optionsReferenceValue = 'BlogPost';
const ReferenceResource = 'OtherResource';
beforeEach(() => {
property = new BaseProperty({
path: 'externalId',
type: 'reference'
});
sinon.stub(property, 'reference').returns(rawReferenceValue);
args.admin.findResource.returns(ReferenceResource);
});
it('returns model from AdminJS for reference name in properties', () => {
new PropertyDecorator({
...args,
property
}).reference();
expect(args.admin.findResource).to.have.been.calledWith(rawReferenceValue);
});
it('returns model from options when they are given', () => {
new PropertyDecorator({
...args,
property,
options: {
reference: optionsReferenceValue
}
}).reference();
expect(args.admin.findResource).to.have.been.calledWith(optionsReferenceValue);
});
});
describe('#type', () => {
const propertyType = 'boolean';
beforeEach(() => {
property = new BaseProperty({
path: 'externalId',
type: propertyType
});
});
it('returns `reference` type if reference is set in options', () => {
const decorator = new PropertyDecorator({
...args,
property,
options: {
reference: 'SomeReference'
}
});
expect(decorator.type()).to.equal('reference');
});
it('returns property reference when no options are given', () => {
const decorator = new PropertyDecorator({
...args,
property
});
expect(decorator.type()).to.equal(propertyType);
});
});
describe('#availableValues', () => {
it('map default value to { value, label } object and uses translations', () => {
sinon.stub(BaseProperty.prototype, 'availableValues').returns(['val']);
expect(new PropertyDecorator(args).availableValues()).to.deep.equal([{
value: 'val',
label: 'val'
}]);
});
});
describe('#position', () => {
it('returns -1 for title field', () => {
sinon.stub(BaseProperty.prototype, 'isTitle').returns(true);
expect(new PropertyDecorator(args).position()).to.equal(-1);
});
it('returns 101 for second field', () => {
sinon.stub(BaseProperty.prototype, 'isTitle').returns(false);
expect(new PropertyDecorator(args).position()).to.equal(101);
});
it('returns 0 for an id field', () => {
sinon.stub(BaseProperty.prototype, 'isTitle').returns(false);
sinon.stub(BaseProperty.prototype, 'isId').returns(true);
expect(new PropertyDecorator(args).position()).to.equal(0);
});
});
describe('#subProperties', () => {
let propertyDecorator;
const propertyName = 'super';
const subPropertyName = 'nested';
const subPropertyLabel = 'nestedLabel';
beforeEach(() => {
property = new BaseProperty({
path: propertyName,
type: 'string'
});
sinon.stub(property, 'subProperties').returns([new BaseProperty({
path: subPropertyName,
type: 'string'
})]);
propertyDecorator = new PropertyDecorator({
...args,
property,
resource: {
id: () => 'resourceId',
options: {
properties: {
[`${propertyName}.${subPropertyName}`]: {
label: subPropertyLabel
}
}
}
}
});
});
it('returns the array of decorated properties', () => {
expect(propertyDecorator.subProperties()).to.have.lengthOf(1);
expect(propertyDecorator.subProperties()[0]).to.be.instanceOf(PropertyDecorator);
});
it('changes label of the nested property to what was given in PropertyOptions', () => {
const subProperty = propertyDecorator.subProperties()[0];
expect(subProperty.label()).to.eq(`${propertyName}.${subPropertyName}`);
});
});
describe('#toJSON', () => {
it('returns JSON representation of a property', () => {
expect(new PropertyDecorator(args).toJSON()).to.have.keys('isTitle', 'isId', 'position', 'isSortable', 'availableValues', 'name', 'label', 'type', 'reference', 'components', 'isDisabled', 'subProperties', 'isArray', 'isDraggable', 'custom', 'resourceId', 'propertyPath', 'isRequired', 'isVirtual', 'props', 'hideLabel', 'description');
});
});
afterEach(() => {
sinon.restore();
});
});