snapshot of https://github.com/espocrm/espocrm.git (master, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s
This commit is contained in:
73
frontend/test/spec/test.acl-manager.js
Normal file
73
frontend/test/spec/test.acl-manager.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('acl-manager', () => {
|
||||
let acl;
|
||||
|
||||
beforeEach(function (done) {
|
||||
require('acl-manager', Acl => {
|
||||
acl = new Acl();
|
||||
|
||||
acl.user = {
|
||||
isAdmin: () => false
|
||||
};
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should check an access properly", () => {
|
||||
acl.set({
|
||||
table: {
|
||||
Lead: {
|
||||
read: 'team',
|
||||
edit: 'own',
|
||||
delete: 'no',
|
||||
},
|
||||
Opportunity: false,
|
||||
Meeting: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(acl.check('Lead', 'read')).toBe(true);
|
||||
|
||||
expect(acl.check('Lead', 'read', false, false)).toBe(true);
|
||||
expect(acl.check('Lead', 'read', false, true)).toBe(true);
|
||||
expect(acl.check('Lead', 'read', true)).toBe(true);
|
||||
|
||||
expect(acl.check('Lead', 'edit')).toBe(true);
|
||||
expect(acl.check('Lead', 'edit', false, true)).toBe(true);
|
||||
expect(acl.check('Lead', 'edit', true, false)).toBe(true);
|
||||
|
||||
expect(acl.check('Lead', 'delete')).toBe(false);
|
||||
|
||||
expect(acl.check('Account', 'edit')).toBe(false);
|
||||
|
||||
expect(acl.check('Opportunity', 'edit')).toBe(false);
|
||||
expect(acl.check('Meeting', 'edit')).toBe(true);
|
||||
});
|
||||
});
|
||||
42
frontend/test/spec/test.cache.js
Normal file
42
frontend/test/spec/test.cache.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('cache', () => {
|
||||
let cache;
|
||||
|
||||
beforeEach(function (done) {
|
||||
require('cache', Cache => {
|
||||
cache = new Cache();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should have \'cache\' prefix', () => {
|
||||
expect(cache.prefix).toBe('cache');
|
||||
});
|
||||
});
|
||||
196
frontend/test/spec/test.collection.js
Normal file
196
frontend/test/spec/test.collection.js
Normal file
@@ -0,0 +1,196 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('collection', () => {
|
||||
let collection;
|
||||
|
||||
/** @type {typeof import('collection').default} */
|
||||
let CollectionClass;
|
||||
/** @type {typeof import('model').default} */
|
||||
let ModelClass;
|
||||
|
||||
beforeEach(done => {
|
||||
Espo.loader.require(['collection', 'model'], (Collection, Model) => {
|
||||
CollectionClass = Collection;
|
||||
ModelClass = Model;
|
||||
|
||||
const m1 = new Model({id: '1'});
|
||||
const m2 = new Model({id: '2'});
|
||||
const m3 = new Model({id: '3'});
|
||||
|
||||
collection = new Collection([m1, m2, m3], {
|
||||
entityType: 'Some',
|
||||
});
|
||||
|
||||
collection.maxSize = 5;
|
||||
|
||||
spyOn(collection, 'fetch').and.returnValue(true);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct length', () => {
|
||||
expect(collection.length).toBe(3);
|
||||
|
||||
const collection2 = new CollectionClass();
|
||||
expect(collection2.length).toBe(0);
|
||||
|
||||
const collection3 = new CollectionClass([new ModelClass({id: '1'})]);
|
||||
expect(collection3.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should add array', () => {
|
||||
const model = new ModelClass({id: '4'});
|
||||
|
||||
collection.add([model]);
|
||||
|
||||
expect(collection.length).toBe(4);
|
||||
expect(collection.at(3)).toBe(model);
|
||||
expect(collection.get('4')).toBe(model);
|
||||
expect(collection.has('4')).toBeTrue();
|
||||
expect(collection.indexOf(model)).toBe(3);
|
||||
});
|
||||
|
||||
it('should add one', () => {
|
||||
const model = new ModelClass({id: '4'});
|
||||
|
||||
collection.add(model, {at: 1});
|
||||
|
||||
expect(collection.length).toBe(4);
|
||||
expect(collection.at(1)).toBe(model);
|
||||
});
|
||||
|
||||
it('should reset', () => {
|
||||
collection.reset();
|
||||
|
||||
expect(collection.length).toBe(0);
|
||||
expect(collection.at(3)).toBeUndefined();
|
||||
expect(collection.get('3')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should remove', () => {
|
||||
collection.remove(collection.get('2'));
|
||||
|
||||
expect(collection.length).toBe(2);
|
||||
expect(collection.get('2')).toBeUndefined();
|
||||
|
||||
collection.remove('1');
|
||||
|
||||
expect(collection.length).toBe(1);
|
||||
expect(collection.get('1')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should push', () => {
|
||||
const model = new ModelClass({id: '4'});
|
||||
|
||||
collection.push(model);
|
||||
|
||||
expect(collection.length).toBe(4);
|
||||
expect(collection.at(3).id).toBe('4');
|
||||
});
|
||||
|
||||
it('should unshift', () => {
|
||||
const model = new ModelClass({id: '4'});
|
||||
|
||||
collection.unshift(model);
|
||||
|
||||
expect(collection.length).toBe(4);
|
||||
expect(collection.at(0).id).toBe('4');
|
||||
});
|
||||
|
||||
it('should pop', () => {
|
||||
const model = collection.pop();
|
||||
|
||||
expect(collection.length).toBe(2);
|
||||
expect(model.id).toBe('3');
|
||||
expect(collection.has('3')).toBeFalse();
|
||||
});
|
||||
|
||||
it('should shift', () => {
|
||||
const model = collection.shift();
|
||||
|
||||
expect(collection.length).toBe(2);
|
||||
expect(model.id).toBe('1');
|
||||
});
|
||||
|
||||
it('should for-each', () => {
|
||||
const ids = [];
|
||||
|
||||
collection.forEach(m => ids.push(m.id));
|
||||
|
||||
expect(ids).toEqual(['1', '2', '3']);
|
||||
});
|
||||
|
||||
it('should have entityType', () => {
|
||||
expect(collection.entityType).toBe('Some');
|
||||
expect(collection.name).toBe('Some');
|
||||
});
|
||||
|
||||
it('should be created with models', () => {
|
||||
expect(collection.length).toBe(3);
|
||||
});
|
||||
|
||||
it('#sort should set order params', () => {
|
||||
collection.sort('test', true);
|
||||
expect(collection.orderBy).toBe('test');
|
||||
expect(collection.order).toBe('desc');
|
||||
});
|
||||
|
||||
it('#nextPage and #previousPage should change offset to the next and previous pages', () => {
|
||||
collection.total = 16;
|
||||
|
||||
collection.add([
|
||||
{id: '1'},
|
||||
{id: '2'},
|
||||
{id: '3'},
|
||||
{id: '4'},
|
||||
{id: '5'},
|
||||
]);
|
||||
|
||||
collection.nextPage();
|
||||
expect(collection.offset).toBe(5);
|
||||
|
||||
collection.nextPage();
|
||||
collection.previousPage();
|
||||
expect(collection.offset).toBe(5);
|
||||
|
||||
collection.previousPage();
|
||||
expect(collection.offset).toBe(0);
|
||||
});
|
||||
|
||||
it('#firstPage and #lastPage should change offset appropriate way', () => {
|
||||
collection.total = 16;
|
||||
|
||||
collection.firstPage();
|
||||
expect(collection.offset).toBe(0);
|
||||
|
||||
collection.lastPage();
|
||||
expect(collection.offset).toBe(15);
|
||||
});
|
||||
});
|
||||
74
frontend/test/spec/test.controller.js
Normal file
74
frontend/test/spec/test.controller.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('controller', () => {
|
||||
let controller;
|
||||
let viewFactory;
|
||||
let view;
|
||||
|
||||
let ControllerClass;
|
||||
|
||||
beforeEach(done => {
|
||||
Espo.loader.require('controller', Controller => {
|
||||
ControllerClass = Controller;
|
||||
|
||||
viewFactory = {
|
||||
create: {}
|
||||
};
|
||||
|
||||
view = {
|
||||
render: {},
|
||||
setView: {}
|
||||
};
|
||||
|
||||
controller = new Controller({}, {viewFactory: viewFactory});
|
||||
spyOn(viewFactory, 'create').and.returnValue(view);
|
||||
spyOn(view, 'render');
|
||||
spyOn(view, 'setView');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it ('#set should set param', () => {
|
||||
controller.set('some', 'test');
|
||||
expect(controller.params['some']).toBe('test');
|
||||
});
|
||||
|
||||
it ('#get should get param', () => {
|
||||
controller.set('some', 'test');
|
||||
expect(controller.get('some')).toBe('test');
|
||||
});
|
||||
|
||||
it ("different controllers should use same param set", () => {
|
||||
const someController = new ControllerClass(controller.params, {viewFactory: viewFactory});
|
||||
|
||||
someController.set('some', 'test');
|
||||
expect(controller.get('some')).toBe(someController.get('some'));
|
||||
});
|
||||
});
|
||||
94
frontend/test/spec/test.date-time.js
Normal file
94
frontend/test/spec/test.date-time.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('date-time', () => {
|
||||
let dateTime;
|
||||
|
||||
beforeEach(done => {
|
||||
require('date-time', DateTime => {
|
||||
dateTime = new DateTime();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should convert date from display format", () => {
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
expect(dateTime.fromDisplayDate('10/05/2013')).toBe('2013-10-05');
|
||||
|
||||
dateTime.dateFormat = 'DD.MM.YYYY';
|
||||
expect(dateTime.fromDisplayDate('05.10.2013')).toBe('2013-10-05');
|
||||
|
||||
dateTime.dateFormat = 'YYYY-MM-DD';
|
||||
expect(dateTime.fromDisplayDate('2013-10-05')).toBe('2013-10-05');
|
||||
});
|
||||
|
||||
it("should convert date to display format", () => {
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
expect(dateTime.toDisplayDate('2013-10-05')).toBe('10/05/2013');
|
||||
|
||||
dateTime.dateFormat = 'DD.MM.YYYY';
|
||||
expect(dateTime.toDisplayDate('2013-10-05')).toBe('05.10.2013');
|
||||
|
||||
dateTime.dateFormat = 'YYYY-MM-DD';
|
||||
expect(dateTime.toDisplayDate('2013-10-05')).toBe('2013-10-05');
|
||||
});
|
||||
|
||||
it("should convert date/time from display format and consider timezone", () => {
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
dateTime.timeFormat = 'hh:mm A';
|
||||
expect(dateTime.fromDisplay('10/05/2013 02:45 PM')).toBe('2013-10-05 14:45:00');
|
||||
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
dateTime.timeFormat = 'hh:mm a';
|
||||
expect(dateTime.fromDisplay('10/05/2013 02:45 pm')).toBe('2013-10-05 14:45:00');
|
||||
|
||||
dateTime.dateFormat = 'DD.MM.YYYY';
|
||||
dateTime.timeFormat = 'HH:mm';
|
||||
expect(dateTime.fromDisplay('05.10.2013 14:45')).toBe('2013-10-05 14:45:00');
|
||||
|
||||
dateTime.timeZone = 'Europe/Kiev';
|
||||
expect(dateTime.fromDisplay('05.10.2013 17:45')).toBe('2013-10-05 14:45:00');
|
||||
});
|
||||
|
||||
it("should convert date/time to display format and consider timezone", () => {
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
dateTime.timeFormat = 'hh:mm A';
|
||||
expect(dateTime.toDisplay('2013-10-05 14:45')).toBe('10/05/2013 02:45 PM');
|
||||
|
||||
dateTime.dateFormat = 'MM/DD/YYYY';
|
||||
dateTime.timeFormat = 'hh:mm a';
|
||||
expect(dateTime.toDisplay('2013-10-05 14:45')).toBe('10/05/2013 02:45 pm');
|
||||
|
||||
dateTime.dateFormat = 'DD.MM.YYYY';
|
||||
dateTime.timeFormat = 'HH:mm';
|
||||
expect(dateTime.toDisplay('2013-10-05 14:45')).toBe('05.10.2013 14:45');
|
||||
|
||||
dateTime.timeZone = 'Europe/Kiev';
|
||||
expect(dateTime.toDisplay('2013-10-05 14:45')).toBe('05.10.2013 17:45');
|
||||
});
|
||||
});
|
||||
209
frontend/test/spec/test.field-manager.js
Normal file
209
frontend/test/spec/test.field-manager.js
Normal file
@@ -0,0 +1,209 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('field-manager', () => {
|
||||
let fieldManager;
|
||||
|
||||
const defs = {
|
||||
'varchar': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
},
|
||||
{
|
||||
'name': 'maxLength',
|
||||
'type': 'int'
|
||||
}
|
||||
]
|
||||
},
|
||||
'int': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
},
|
||||
{
|
||||
'name': 'min',
|
||||
'type': 'int'
|
||||
},
|
||||
{
|
||||
'name': 'max',
|
||||
'type': 'int'
|
||||
}
|
||||
]
|
||||
},
|
||||
'float': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
},
|
||||
{
|
||||
'name': 'min',
|
||||
'type': 'float'
|
||||
},
|
||||
{
|
||||
'name': 'max',
|
||||
'type': 'float'
|
||||
}
|
||||
]
|
||||
},
|
||||
'enum': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
},
|
||||
{
|
||||
'name': 'options',
|
||||
'type': 'array'
|
||||
}
|
||||
]
|
||||
},
|
||||
'bool': {
|
||||
'params': []
|
||||
},
|
||||
'date': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
}
|
||||
]
|
||||
},
|
||||
'datetime': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
}
|
||||
]
|
||||
},
|
||||
'link': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
}
|
||||
],
|
||||
'actualFields': ['id']
|
||||
},
|
||||
'linkParent': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
}
|
||||
],
|
||||
'actualFields': ['id', 'type']
|
||||
},
|
||||
'linkMultiple': {
|
||||
'params': [
|
||||
{
|
||||
'name': 'required',
|
||||
'type': 'bool',
|
||||
'default': false
|
||||
}
|
||||
],
|
||||
'actualFields': ['ids']
|
||||
},
|
||||
'personName': {
|
||||
'actualFields': ['salutation', 'first', 'last'],
|
||||
'fields': {
|
||||
'salutation': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
'first': {
|
||||
'type': 'enum'
|
||||
},
|
||||
'last': {
|
||||
'type': 'varchar'
|
||||
}
|
||||
},
|
||||
'naming': 'prefix',
|
||||
'notMergeable': true,
|
||||
},
|
||||
'address': {
|
||||
'actualFields': ['street', 'city', 'state', 'country', 'postalCode'],
|
||||
'fields': {
|
||||
'street': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
'city': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
'state': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
'country': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
'postalCode': {
|
||||
'type': 'varchar'
|
||||
},
|
||||
},
|
||||
'notMergeable': true
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(done => {
|
||||
require(['field-manager', 'utils'], FieldManager => {
|
||||
fieldManager = new FieldManager(defs);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it ('#isMergable should work correctly', () => {
|
||||
expect(fieldManager.isMergeable('address')).toBe(false);
|
||||
expect(fieldManager.isMergeable('link')).toBe(true);
|
||||
});
|
||||
|
||||
it ('#getActualAttributeList should work correctly', () => {
|
||||
let fields = fieldManager.getActualAttributeList('address', 'billingAddress');
|
||||
|
||||
expect(fields[0]).toBe('billingAddressStreet');
|
||||
|
||||
fields = fieldManager.getActualAttributeList('personName', 'name');
|
||||
expect(fields[2]).toBe('lastName');
|
||||
|
||||
fields = fieldManager.getActualAttributeList('link', 'account');
|
||||
expect(fields[0]).toBe('accountId');
|
||||
|
||||
fields = fieldManager.getActualAttributeList('varchar', 'name');
|
||||
expect(fields[0]).toBe('name');
|
||||
});
|
||||
});
|
||||
48
frontend/test/spec/test.layout-manager.js
Normal file
48
frontend/test/spec/test.layout-manager.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('layout-manager', () => {
|
||||
let layoutManager;
|
||||
|
||||
beforeEach((done) => {
|
||||
require('layout-manager', (LayoutManager) => {
|
||||
layoutManager = new LayoutManager();
|
||||
spyOn(layoutManager.ajax, 'getRequest')
|
||||
.and
|
||||
.callFake((options) => Promise.resolve());
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should call ajax to fetch new layout", () => {
|
||||
layoutManager.get('some', 'list');
|
||||
|
||||
expect(layoutManager.ajax.getRequest.calls.mostRecent().args[0]).toBe('some/layout/list');
|
||||
});
|
||||
});
|
||||
50
frontend/test/spec/test.metadata.js
Normal file
50
frontend/test/spec/test.metadata.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('metadata', () => {
|
||||
let metadata;
|
||||
|
||||
beforeEach(done => {
|
||||
require('metadata', Metadata => {
|
||||
metadata = new Metadata();
|
||||
metadata.data = {
|
||||
recordDefs: {
|
||||
Lead: {
|
||||
some: {type: 'varchar'},
|
||||
}
|
||||
}
|
||||
};
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('#get should work correctly', () => {
|
||||
expect(metadata.get('recordDefs.Lead.some')).toBe(metadata.data.recordDefs.Lead.some);
|
||||
expect(metadata.get('recordDefs.Contact')).toBe(null);
|
||||
});
|
||||
});
|
||||
245
frontend/test/spec/test.model.js
Normal file
245
frontend/test/spec/test.model.js
Normal file
@@ -0,0 +1,245 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('model', () => {
|
||||
let model;
|
||||
|
||||
beforeEach(done => {
|
||||
Espo.loader.require(['model', 'utils'], ModelBase => {
|
||||
const Model = class extends ModelBase {};
|
||||
|
||||
model = new Model({}, {
|
||||
entityType: 'Some',
|
||||
defs: {
|
||||
fields: {
|
||||
'id': {
|
||||
type: 'id',
|
||||
},
|
||||
'name': {
|
||||
maxLength: 150,
|
||||
required: true,
|
||||
},
|
||||
'email': {
|
||||
type: 'email',
|
||||
},
|
||||
'phone': {
|
||||
type: 'phone',
|
||||
maxLength: 50,
|
||||
default: '007',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set urlRoot as name', () => {
|
||||
expect(model.urlRoot).toBe('Some');
|
||||
});
|
||||
|
||||
it('#getFieldType should return field type or null if undefined', () => {
|
||||
expect(model.getFieldType('email')).toBe('email');
|
||||
expect(model.getFieldType('name')).toBe(null);
|
||||
});
|
||||
|
||||
it('#isRequired should return true if field is required and false if not', () => {
|
||||
expect(model.isRequired('name')).toBe(true);
|
||||
expect(model.isRequired('email')).toBe(false);
|
||||
});
|
||||
|
||||
it('should set defaults correctly', () => {
|
||||
model.populateDefaults();
|
||||
expect(model.get('phone')).toBe('007');
|
||||
});
|
||||
|
||||
it('should fire change event on set 1', () => {
|
||||
return new Promise(resolve => {
|
||||
model.once('change', () => {
|
||||
expect(model.get('name')).toBe('test');
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.set('name', 'test');
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire change event on set 2', () => {
|
||||
return new Promise(resolve => {
|
||||
model.once('change:name', (m, v) => {
|
||||
expect(model.get('name')).toBe('test');
|
||||
expect(v).toBe('test');
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.set({'name': 'test'});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fire change event on set with silent option', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
model.once('change:name', () => {
|
||||
reject();
|
||||
});
|
||||
|
||||
model.once('change:hello', (m, v, o) => {
|
||||
expect(o.test).toBe(true);
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.setMultiple({'name': 'test'}, {silent: true});
|
||||
model.setMultiple({'hello': 'hello'}, {test: true});
|
||||
});
|
||||
});
|
||||
|
||||
it('should unset attribute', () => {
|
||||
model.set('name', 'test');
|
||||
|
||||
expect(model.has('name')).toBeTrue();
|
||||
|
||||
model.unset('name');
|
||||
|
||||
expect(model.has('name')).toBeFalse();
|
||||
});
|
||||
|
||||
it('should unset attribute and fire events', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
model.setMultiple({
|
||||
'name': '1',
|
||||
'hello': 1,
|
||||
});
|
||||
|
||||
model.once('change:name', () => {
|
||||
reject();
|
||||
});
|
||||
|
||||
model.once('change:hello', (m, v, o) => {
|
||||
expect(o.test).toBe(true);
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.unset('name', {silent: true});
|
||||
model.unset('hello', {test: true});
|
||||
});
|
||||
});
|
||||
|
||||
it('should clear attributes', () => {
|
||||
model.set('name', 'test');
|
||||
|
||||
expect(model.has('name')).toBeTrue();
|
||||
|
||||
model.clear();
|
||||
|
||||
expect(model.has('name')).toBeFalse();
|
||||
});
|
||||
|
||||
it('should update with PUT', () => {
|
||||
model.id = '000';
|
||||
model.set('test1', '1');
|
||||
model.set('test2', '2');
|
||||
|
||||
return new Promise(resolve => {
|
||||
model.on('request', (url, method, data) => {
|
||||
expect(url).toBe('Some/000');
|
||||
expect(method).toBe('PUT');
|
||||
expect(data).toEqual({
|
||||
test1: '1',
|
||||
test2: '2',
|
||||
test3: '3',
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.save({test3: '3'}, {bypassRequest: true});
|
||||
});
|
||||
});
|
||||
|
||||
it('should patch with PUT', () => {
|
||||
model.id = '000';
|
||||
model.set('test1', '1');
|
||||
model.set('test2', '2');
|
||||
|
||||
return new Promise(resolve => {
|
||||
model.on('request', (url, method, data) => {
|
||||
expect(url).toBe('Some/000');
|
||||
expect(method).toBe('PUT');
|
||||
expect(data).toEqual({
|
||||
test3: '3',
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.save({test3: '3'}, {bypassRequest: true, patch: true});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create with POST', () => {
|
||||
model.set('test1', '1');
|
||||
model.set('test2', '2');
|
||||
|
||||
return new Promise(resolve => {
|
||||
model.on('request', (url, method, data) => {
|
||||
expect(url).toBe('Some');
|
||||
expect(method).toBe('POST');
|
||||
expect(data).toEqual({
|
||||
test1: '1',
|
||||
test2: '2',
|
||||
test3: '3',
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.save({test3: '3'}, {bypassRequest: true});
|
||||
});
|
||||
});
|
||||
|
||||
it('should destroy with DELETE', () => {
|
||||
model.id = '000';
|
||||
model.set('test1', '1');
|
||||
model.set('test2', '2');
|
||||
|
||||
return new Promise(resolve => {
|
||||
model.on('request', (url, method) => {
|
||||
expect(url).toBe('Some/000');
|
||||
expect(method).toBe('DELETE');
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
model.destroy({bypassRequest: true});
|
||||
});
|
||||
});
|
||||
});
|
||||
57
frontend/test/spec/test.router.js
Normal file
57
frontend/test/spec/test.router.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('router', () => {
|
||||
let router;
|
||||
|
||||
beforeEach(done => {
|
||||
require('router', Router => {
|
||||
router = new Router();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse slashed options', () => {
|
||||
let options = router._parseOptionsParams("p=1&t=2");
|
||||
expect(options.p).toBe('1');
|
||||
expect(options.t).toBe('2');
|
||||
|
||||
options = router._parseOptionsParams("p=1&");
|
||||
expect(options.p).toBe('1');
|
||||
|
||||
options = router._parseOptionsParams("p");
|
||||
expect(options).toBe("p");
|
||||
|
||||
options = router._parseOptionsParams("p=1&t");
|
||||
expect(options.p).toBe('1');
|
||||
expect(options.t).toBe(true);
|
||||
|
||||
options = router._parseOptionsParams("p=1&t=");
|
||||
expect(options.t).toBe('');
|
||||
});
|
||||
});
|
||||
233
frontend/test/spec/test.theme-manager.js
Normal file
233
frontend/test/spec/test.theme-manager.js
Normal file
@@ -0,0 +1,233 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('theme-manager', () => {
|
||||
/** @type {module:models/settings} */
|
||||
let config;
|
||||
/** @type {module:models/preferences} */
|
||||
let preferences;
|
||||
/** @type {module:metadata} */
|
||||
let metadata;
|
||||
/** @type {module:theme-manager} */
|
||||
let themeManager;
|
||||
|
||||
beforeEach(done => {
|
||||
require(['models/settings', 'models/preferences', 'metadata', 'theme-manager'],
|
||||
(Config, Preferences, Metadata, ThemeManager) => {
|
||||
config = new Config();
|
||||
preferences = new Preferences();
|
||||
metadata = new Metadata();
|
||||
themeManager = new ThemeManager(config, preferences, metadata)
|
||||
|
||||
metadata.data = {
|
||||
themes: {
|
||||
"Espo": {
|
||||
"params": {
|
||||
"navbar": {
|
||||
"type": "enum",
|
||||
"default": "side",
|
||||
"options": [
|
||||
"side",
|
||||
"top"
|
||||
]
|
||||
},
|
||||
"direction": {
|
||||
"type": "enum",
|
||||
"default": "ltr",
|
||||
"options": [
|
||||
"ltr",
|
||||
"rtl"
|
||||
]
|
||||
}
|
||||
},
|
||||
"mappedParams": {
|
||||
"navbarHeight": {
|
||||
"param": "navbar",
|
||||
"valueMap": {
|
||||
"side": 30,
|
||||
"top": 43
|
||||
}
|
||||
}
|
||||
},
|
||||
"someParam": "someValue"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('name', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getName()).toBe('Test');
|
||||
});
|
||||
|
||||
it('param', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Espo';
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('someParam')).toBe('someValue');
|
||||
});
|
||||
|
||||
it('parent param', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('someParam')).toBe('someValue');
|
||||
});
|
||||
|
||||
it('default param', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('navbar')).toBe('side');
|
||||
});
|
||||
|
||||
it('param from preferences', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
navbar: 'top',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('navbar')).toBe('top');
|
||||
});
|
||||
|
||||
it('param from config', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
spyOn(config, 'get').and.callFake(name => {
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
navbar: 'top',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('navbar')).toBe('top');
|
||||
});
|
||||
|
||||
it('direction default', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Espo';
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getDirection()).toBe('ltr');
|
||||
});
|
||||
|
||||
it('direction from preferences', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Espo';
|
||||
}
|
||||
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
direction: 'rtl',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getDirection()).toBe('rtl');
|
||||
});
|
||||
|
||||
it('invalid direction', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Espo';
|
||||
}
|
||||
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
direction: 'invalid',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getDirection()).toBe('ltr');
|
||||
});
|
||||
|
||||
it('mapped param 1', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
navbar: 'top',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('navbarHeight')).toBe(43);
|
||||
});
|
||||
|
||||
it('mapped param 2', () => {
|
||||
spyOn(preferences, 'get').and.callFake(name => {
|
||||
if (name === 'theme') {
|
||||
return 'Test';
|
||||
}
|
||||
|
||||
if (name === 'themeParams') {
|
||||
return {
|
||||
navbar: 'side',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
expect(themeManager.getParam('navbarHeight')).toBe(30);
|
||||
});
|
||||
});
|
||||
234
frontend/test/spec/test.utils.js
Normal file
234
frontend/test/spec/test.utils.js
Normal file
@@ -0,0 +1,234 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
describe('utils', () => {
|
||||
let Utils;
|
||||
|
||||
beforeEach(done => {
|
||||
require(['utils'], UtilsD => {
|
||||
Utils = UtilsD;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('#upperCaseFirst should make first letter uppercase', () => {
|
||||
expect(Utils.upperCaseFirst('someTest')).toBe('SomeTest');
|
||||
});
|
||||
|
||||
it('#checkAccessDataList should check access 1', () => {
|
||||
const user = {
|
||||
isPortal: () => {
|
||||
},
|
||||
getLinkMultipleIdList: () => {
|
||||
},
|
||||
isAdmin: () => {
|
||||
}
|
||||
};
|
||||
const acl = {
|
||||
check: () => {
|
||||
},
|
||||
checkScope: () => {
|
||||
}
|
||||
};
|
||||
const entity = {
|
||||
name: 'Account'
|
||||
};
|
||||
spyOn(user, 'getLinkMultipleIdList').and.callFake(link => {
|
||||
if (link === 'teams') {
|
||||
return ['team1', 'team2'];
|
||||
}
|
||||
if (link === 'portals') {
|
||||
return ['portal1', 'portal2'];
|
||||
}
|
||||
});
|
||||
spyOn(user, 'isPortal').and.returnValue(false);
|
||||
spyOn(user, 'isAdmin').and.returnValue(false);
|
||||
|
||||
spyOn(acl, 'checkScope').and.callFake(function (scope) {
|
||||
if (scope === 'Account') {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
spyOn(acl, 'check').and.callFake(function (obj, action) {
|
||||
if (obj === 'Account') {
|
||||
return {
|
||||
create: true,
|
||||
read: true,
|
||||
edit: true,
|
||||
delete: false
|
||||
}[action];
|
||||
}
|
||||
if (obj.name) {
|
||||
return {
|
||||
create: true,
|
||||
read: true,
|
||||
edit: false,
|
||||
delete: false
|
||||
}[action];
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
], acl, user)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
scope: 'Account'
|
||||
}
|
||||
], acl, user)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
scope: 'Account',
|
||||
action: 'delete'
|
||||
}
|
||||
], acl, user)).toBe(false);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
scope: 'Account',
|
||||
action: 'read'
|
||||
},
|
||||
{
|
||||
inPortalDisabled: true
|
||||
}
|
||||
], acl, user)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
action: 'read'
|
||||
},
|
||||
{
|
||||
teamIdList: ['team1', 'team3']
|
||||
}
|
||||
], acl, user, entity)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
isPortalOnly: true
|
||||
}
|
||||
], acl, user)).toBe(false);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
isAdminOnly: true
|
||||
}
|
||||
], acl, user)).toBe(false);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
action: 'edit'
|
||||
}
|
||||
], acl, user, entity)).toBe(false);
|
||||
});
|
||||
|
||||
it('#checkAccessDataList should check access 2', () => {
|
||||
const user = {
|
||||
isPortal: () => {
|
||||
},
|
||||
getLinkMultipleIdList: () => {
|
||||
},
|
||||
isAdmin: () => {
|
||||
}
|
||||
};
|
||||
const acl = {
|
||||
check: () => {
|
||||
},
|
||||
checkScope: () => {
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(user, 'getLinkMultipleIdList').and.callFake(link => {
|
||||
if (link === 'teams') {
|
||||
return ['team1', 'team2'];
|
||||
}
|
||||
|
||||
if (link === 'portals') {
|
||||
return ['portal1', 'portal2'];
|
||||
}
|
||||
});
|
||||
spyOn(user, 'isPortal').and.returnValue(true);
|
||||
spyOn(user, 'isAdmin').and.returnValue(false);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
isPortalOnly: true
|
||||
}
|
||||
], acl, user)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
portalIdList: ['portal2', 'portal3']
|
||||
}
|
||||
], acl, user)).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it('#checkAccessDataList should check access 3', () => {
|
||||
const user = {
|
||||
isPortal: function () {
|
||||
},
|
||||
getLinkMultipleIdList: function () {
|
||||
},
|
||||
isAdmin: function () {
|
||||
}
|
||||
};
|
||||
const acl = {
|
||||
check: function () {
|
||||
},
|
||||
checkScope: function () {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
spyOn(user, 'getLinkMultipleIdList').and.callFake(link => {
|
||||
if (link === 'teams') {
|
||||
return ['team1', 'team2'];
|
||||
}
|
||||
if (link === 'portals') {
|
||||
return ['portal1', 'portal2'];
|
||||
}
|
||||
});
|
||||
|
||||
spyOn(user, 'isPortal').and.returnValue(false);
|
||||
spyOn(user, 'isAdmin').and.returnValue(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
portalIdList: ['portal3']
|
||||
}
|
||||
], acl, user, null, true)).toBe(true);
|
||||
|
||||
expect(Utils.checkAccessDataList([
|
||||
{
|
||||
teamIdList: ['team3']
|
||||
}
|
||||
], acl, user, null, true)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user