Merge branch 'v8/dev' into v8/contrib
# Conflicts: # src/Umbraco.Web.UI.Client/package.json # src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js # src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js # src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js # src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html # src/Umbraco.Web.UI.Client/src/views/content/overlays/publishdescendants.controller.js # src/Umbraco.Web.UI.Client/src/views/content/overlays/publishdescendants.html # src/Umbraco.Web.UI.Client/src/views/dictionary/edit.html # src/Umbraco.Web.UI/Umbraco/config/lang/en.xml
This commit is contained in:
@@ -53,7 +53,6 @@
|
||||
testCases.forEach(function(test){
|
||||
|
||||
it('Expects \'' + test.input + '\' to be truncated as \''+ test.expectedResult + '\', when noOfChars=' + test.noOfChars + ', and appendDots=' + test.appendDots, function() {
|
||||
console.log($truncate(test.input, test.noOfChars, test.appendDots));
|
||||
expect($truncate(test.input, test.noOfChars, test.appendDots)).toBe(test.expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
describe('blockEditorService tests', function () {
|
||||
|
||||
var contentKey = "6A1F5BDD-67EF-4173-B061-D6348ED07094";
|
||||
var contentUdi = "umb://element/6A1F5BDD67EF4173B061D6348ED07094";
|
||||
var settingsKey = "2AF42343-C8A2-400D-BA43-4818C2B3CDC5";
|
||||
var settingsUdi = "umb://element/2AF42343C8A2400DBA434818C2B3CDC5";
|
||||
|
||||
var blockEditorService, contentResource, $rootScope, $scope, $q, localizationService, $timeout;
|
||||
|
||||
beforeEach(module('umbraco.services'));
|
||||
beforeEach(module('umbraco.resources'));
|
||||
beforeEach(module('umbraco.mocks'));
|
||||
beforeEach(module('umbraco'));
|
||||
|
||||
beforeEach(inject(function ($injector, mocksUtils, _$rootScope_, _$q_, _$timeout_) {
|
||||
|
||||
mocksUtils.disableAuth();
|
||||
|
||||
$rootScope = _$rootScope_;
|
||||
$scope = $rootScope.$new();
|
||||
$q = _$q_;
|
||||
$timeout = _$timeout_;
|
||||
|
||||
contentResource = $injector.get("contentResource");
|
||||
spyOn(contentResource, "getScaffoldByKey").and.callFake(
|
||||
function () {
|
||||
var scaffold = mocksUtils.getMockVariantContent(1234, contentKey, contentUdi);
|
||||
return $q.resolve(scaffold);
|
||||
}
|
||||
);
|
||||
// this seems to be required because of the poor promise implementation in localizationService (see TODO in that service)
|
||||
localizationService = $injector.get("localizationService");
|
||||
spyOn(localizationService, "localize").and.callFake(
|
||||
function () {
|
||||
return $q.resolve("Localized test text");
|
||||
}
|
||||
);
|
||||
|
||||
blockEditorService = $injector.get('blockEditorService');
|
||||
|
||||
}));
|
||||
|
||||
|
||||
var blockConfigurationMock = { contentTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB", label: "Test label", settingsElementTypeKey: null, view: "testview.html" };
|
||||
|
||||
var propertyModelMock = {
|
||||
layout: {
|
||||
"Umbraco.TestBlockEditor": [
|
||||
{
|
||||
contentUdi: contentUdi
|
||||
}
|
||||
]
|
||||
},
|
||||
contentData: [
|
||||
{
|
||||
udi: contentUdi,
|
||||
contentTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB",
|
||||
testproperty: "myTestValue"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var blockWithSettingsConfigurationMock = { contentTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB", label: "Test label", settingsElementTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB", view: "testview.html" };
|
||||
var propertyModelWithSettingsMock = {
|
||||
layout: {
|
||||
"Umbraco.TestBlockEditor": [
|
||||
{
|
||||
contentUdi: contentUdi,
|
||||
settingsUdi: settingsUdi
|
||||
}
|
||||
]
|
||||
},
|
||||
contentData: [
|
||||
{
|
||||
udi: contentUdi,
|
||||
contentTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB",
|
||||
testproperty: "myTestValue"
|
||||
}
|
||||
],
|
||||
settingsData: [
|
||||
{
|
||||
udi: settingsUdi,
|
||||
contentTypeKey: "7C5B74D1-E2F9-45A3-AE4B-FC7A829BF8AB",
|
||||
testproperty: "myTestValueForSettings"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
describe('init blockEditorModelObject', function () {
|
||||
|
||||
it('fail if no model value', function () {
|
||||
function createWithNoModelValue() {
|
||||
blockEditorService.createModelObject(null, "Umbraco.TestBlockEditor", [], $scope, $scope);
|
||||
}
|
||||
expect(createWithNoModelValue).toThrow();
|
||||
});
|
||||
|
||||
it('return a object, with methods', function () {
|
||||
var modelObject = blockEditorService.createModelObject({}, "Umbraco.TestBlockEditor", [], $scope, $scope);
|
||||
|
||||
expect(modelObject).not.toBeUndefined();
|
||||
expect(modelObject.load).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it('getBlockConfiguration provide the requested block configurtion', function () {
|
||||
var modelObject = blockEditorService.createModelObject({}, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
expect(modelObject.getBlockConfiguration(blockConfigurationMock.contentTypeKey).label).toBe(blockConfigurationMock.label);
|
||||
});
|
||||
|
||||
it('load provides data for itemPicker', function (done) {
|
||||
var modelObject = blockEditorService.createModelObject({}, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
try {
|
||||
var itemPickerOptions = modelObject.getAvailableBlocksForBlockPicker();
|
||||
expect(itemPickerOptions.length).toBe(1);
|
||||
expect(itemPickerOptions[0].blockConfigModel.contentTypeKey).toBe(blockConfigurationMock.contentTypeKey);
|
||||
done();
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
it('getLayoutEntry has values', function (done) {
|
||||
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModelMock, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
expect(layout).not.toBeUndefined();
|
||||
expect(layout.length).toBe(1);
|
||||
expect(layout[0]).toBe(propertyModelMock.layout["Umbraco.TestBlockEditor"][0]);
|
||||
expect(layout[0].udi).toBe(propertyModelMock.layout["Umbraco.TestBlockEditor"][0].udi);
|
||||
|
||||
done();
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
it('getBlockObject has values', function (done) {
|
||||
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModelMock, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
expect(blockObject).not.toBeUndefined();
|
||||
expect(blockObject.data.udi).toBe(propertyModelMock.contentData[0].udi);
|
||||
expect(blockObject.content.variants[0].tabs[0].properties[0].value).toBe(propertyModelMock.contentData[0].testproperty);
|
||||
|
||||
done();
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
|
||||
it('getBlockObject syncs primitive values', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelMock);
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value = "anotherTestValue";
|
||||
|
||||
// invoke angularJS Store.
|
||||
$timeout(function () {
|
||||
expect(blockObject.data).toEqual(propertyModel.contentData[0]);
|
||||
expect(blockObject.data.testproperty).toBe("anotherTestValue");
|
||||
expect(propertyModel.contentData[0].testproperty).toBe("anotherTestValue");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('getBlockObject syncs values of object', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelMock);
|
||||
|
||||
var complexValue = { "list": ["A", "B", "C"] };
|
||||
propertyModel.contentData[0].testproperty = complexValue;
|
||||
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value.list[0] = "AA";
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value.list.push("D");
|
||||
|
||||
// invoke angularJS Store.
|
||||
$timeout(function () {
|
||||
expect(propertyModel.contentData[0].testproperty.list[0]).toBe("AA");
|
||||
expect(propertyModel.contentData[0].testproperty.list.length).toBe(4);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
it('layout is referencing layout of propertyModel', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelMock);
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
// remove from layout;
|
||||
layout.splice(0, 1);
|
||||
|
||||
expect(propertyModel.layout["Umbraco.TestBlockEditor"].length).toBe(0);
|
||||
expect(propertyModel.layout["Umbraco.TestBlockEditor"][0]).toBeUndefined();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
it('removeDataAndDestroyModel removes data', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelMock);
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
expect(blockObject).not.toBeUndefined();
|
||||
expect(blockObject).not.toBe(null);
|
||||
|
||||
// remove from layout;
|
||||
layout.splice(0, 1);
|
||||
|
||||
// remove from data;
|
||||
modelObject.removeDataAndDestroyModel(blockObject);
|
||||
|
||||
expect(propertyModel.contentData.length).toBe(0);
|
||||
expect(propertyModel.contentData[0]).toBeUndefined();
|
||||
expect(propertyModel.layout["Umbraco.TestBlockEditor"].length).toBe(0);
|
||||
expect(propertyModel.layout["Umbraco.TestBlockEditor"][0]).toBeUndefined();
|
||||
|
||||
done();
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
it('getBlockObject of block with settings has values', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelWithSettingsMock);
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockWithSettingsConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
expect(blockObject).not.toBeUndefined();
|
||||
expect(blockObject.data.udi).toBe(propertyModel.contentData[0].udi);
|
||||
expect(blockObject.content.variants[0].tabs[0].properties[0].value).toBe(propertyModel.contentData[0].testproperty);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
|
||||
it('getBlockObject of block with settings syncs primative values', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelWithSettingsMock);
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockWithSettingsConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value = "anotherTestValue";
|
||||
blockObject.settings.variants[0].tabs[0].properties[0].value = "anotherTestValueForSettings";
|
||||
|
||||
// invoke angularJS Store.
|
||||
$timeout(function () {
|
||||
expect(blockObject.data).toEqual(propertyModel.contentData[0]);
|
||||
expect(blockObject.data.testproperty).toBe("anotherTestValue");
|
||||
expect(propertyModel.contentData[0].testproperty).toBe("anotherTestValue");
|
||||
|
||||
expect(blockObject.settingsData).toEqual(propertyModel.settingsData[0]);
|
||||
expect(blockObject.settingsData.testproperty).toBe("anotherTestValueForSettings");
|
||||
expect(propertyModel.settingsData[0].testproperty).toBe("anotherTestValueForSettings");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
|
||||
it('getBlockObject of block with settings syncs values of object', function (done) {
|
||||
|
||||
var propertyModel = angular.copy(propertyModelWithSettingsMock);
|
||||
|
||||
var complexValue = { "list": ["A", "B", "C"] };
|
||||
propertyModel.contentData[0].testproperty = complexValue;
|
||||
|
||||
var complexSettingsValue = { "list": ["A", "B", "C"] };
|
||||
propertyModel.settingsData[0].testproperty = complexSettingsValue;
|
||||
|
||||
var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockWithSettingsConfigurationMock], $scope, $scope);
|
||||
|
||||
modelObject.load().then(() => {
|
||||
|
||||
try {
|
||||
var layout = modelObject.getLayout();
|
||||
|
||||
var blockObject = modelObject.getBlockObject(layout[0]);
|
||||
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value.list[0] = "AA";
|
||||
blockObject.content.variants[0].tabs[0].properties[0].value.list.push("D");
|
||||
|
||||
blockObject.settings.variants[0].tabs[0].properties[0].value.list[0] = "settingsValue";
|
||||
blockObject.settings.variants[0].tabs[0].properties[0].value.list.push("settingsNewValue");
|
||||
|
||||
// invoke angularJS Store.
|
||||
$timeout(function () {
|
||||
expect(propertyModel.contentData[0].testproperty.list[0]).toBe("AA");
|
||||
expect(propertyModel.contentData[0].testproperty.list.length).toBe(4);
|
||||
|
||||
expect(propertyModel.settingsData[0].testproperty.list[0]).toBe("settingsValue");
|
||||
expect(propertyModel.settingsData[0].testproperty.list.length).toBe(4);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
} catch (e) {
|
||||
done.fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
$timeout.flush();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,10 +1,13 @@
|
||||
describe('serverValidationManager tests', function () {
|
||||
var serverValidationManager;
|
||||
var $rootScope, serverValidationManager, $timeout;
|
||||
|
||||
beforeEach(module('umbraco.services'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
serverValidationManager = $injector.get('serverValidationManager');
|
||||
$rootScope = $injector.get('$rootScope');
|
||||
$timeout = $injector.get('$timeout');
|
||||
serverValidationManager = $injector.get('serverValidationManager');
|
||||
serverValidationManager.clear();
|
||||
}));
|
||||
|
||||
describe('managing field validation errors', function () {
|
||||
@@ -314,6 +317,158 @@
|
||||
|
||||
});
|
||||
|
||||
describe('managing complex editor validation errors', function () {
|
||||
|
||||
// this root element doesn't have it's own attached errors, instead it has model state just
|
||||
// showing that it has errors within it's nested properties. that ModelState is automatically
|
||||
// added on the server side.
|
||||
var nonRootLevelComplexValidationMsg = `[
|
||||
{
|
||||
"$elementTypeAlias": "addressBook",
|
||||
"$id": "34E3A26C-103D-4A05-AB9D-7E14032309C3",
|
||||
"addresses":
|
||||
[
|
||||
{
|
||||
"$elementTypeAlias": "addressInfo",
|
||||
"$id": "FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1",
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.city.invariant.null.country": [
|
||||
"City is not in Australia"
|
||||
],
|
||||
"_Properties.city.invariant.null.capital": [
|
||||
"Not a capital city"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"$elementTypeAlias": "addressInfo",
|
||||
"$id": "7170A4DD-2441-4B1B-A8D3-437D75C4CBC9",
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.city.invariant.null.country": [
|
||||
"City is not in Australia"
|
||||
],
|
||||
"_Properties.city.invariant.null.capital": [
|
||||
"Not a capital city"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.addresses.invariant.null": [
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
]`;
|
||||
|
||||
it('create dictionary of id to ModelState', function () {
|
||||
|
||||
//arrange
|
||||
var complexValidationMsg = `[
|
||||
{
|
||||
"$elementTypeAlias": "addressBook",
|
||||
"$id": "34E3A26C-103D-4A05-AB9D-7E14032309C3",
|
||||
"addresses":
|
||||
[
|
||||
{
|
||||
"$elementTypeAlias": "addressInfo",
|
||||
"$id": "FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1",
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.city.invariant.null.country": [
|
||||
"City is not in Australia"
|
||||
],
|
||||
"_Properties.city.invariant.null.capital": [
|
||||
"Not a capital city"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"$elementTypeAlias": "addressInfo",
|
||||
"$id": "7170A4DD-2441-4B1B-A8D3-437D75C4CBC9",
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.city.invariant.null.country": [
|
||||
"City is not in Australia"
|
||||
],
|
||||
"_Properties.city.invariant.null.capital": [
|
||||
"Not a capital city"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"ModelState":
|
||||
{
|
||||
"_Properties.addresses.invariant.null.counter": [
|
||||
"Must have at least 3 addresses"
|
||||
],
|
||||
"_Properties.bookName.invariant.null.book": [
|
||||
"Invalid address book name"
|
||||
]
|
||||
}
|
||||
}
|
||||
]`;
|
||||
|
||||
//act
|
||||
var ms = serverValidationManager.parseComplexEditorError(complexValidationMsg, "myBlockEditor");
|
||||
|
||||
//assert
|
||||
expect(ms.length).toEqual(3);
|
||||
expect(ms[0].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3");
|
||||
expect(ms[1].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1");
|
||||
expect(ms[2].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/7170A4DD-2441-4B1B-A8D3-437D75C4CBC9");
|
||||
|
||||
});
|
||||
|
||||
it('create dictionary of id to ModelState with inherited errors', function () {
|
||||
|
||||
//act
|
||||
var ms = serverValidationManager.parseComplexEditorError(nonRootLevelComplexValidationMsg, "myBlockEditor");
|
||||
|
||||
//assert
|
||||
expect(ms.length).toEqual(3);
|
||||
expect(ms[0].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3");
|
||||
var item0ModelState = ms[0].modelState;
|
||||
expect(Object.keys(item0ModelState).length).toEqual(1);
|
||||
expect(item0ModelState["_Properties.addresses.invariant.null"].length).toEqual(1);
|
||||
expect(item0ModelState["_Properties.addresses.invariant.null"][0]).toEqual("");
|
||||
expect(ms[1].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1");
|
||||
expect(ms[2].validationPath).toEqual("myBlockEditor/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/7170A4DD-2441-4B1B-A8D3-437D75C4CBC9");
|
||||
|
||||
});
|
||||
|
||||
it('add errors for ModelState with inherited errors', function () {
|
||||
|
||||
//act
|
||||
let modelState = {
|
||||
"_Properties.blockFeatures.invariant.null": [
|
||||
nonRootLevelComplexValidationMsg
|
||||
]
|
||||
};
|
||||
serverValidationManager.addErrorsForModelState(modelState);
|
||||
|
||||
//assert
|
||||
var propertyErrors = [
|
||||
"blockFeatures",
|
||||
"blockFeatures/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses",
|
||||
"blockFeatures/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city",
|
||||
"blockFeatures/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/7170A4DD-2441-4B1B-A8D3-437D75C4CBC9/city"
|
||||
]
|
||||
// These will all exist
|
||||
propertyErrors.forEach(x => expect(serverValidationManager.getPropertyError(x)).toBeDefined());
|
||||
|
||||
// These field errors also exist
|
||||
expect(serverValidationManager.getPropertyError(propertyErrors[2], null, "country")).toBeDefined();
|
||||
expect(serverValidationManager.getPropertyError(propertyErrors[2], null, "capital")).toBeDefined();
|
||||
expect(serverValidationManager.getPropertyError(propertyErrors[3], null, "country")).toBeDefined();
|
||||
expect(serverValidationManager.getPropertyError(propertyErrors[3], null, "capital")).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('validation error subscriptions', function() {
|
||||
|
||||
it('can subscribe to a field error', function() {
|
||||
@@ -327,7 +482,9 @@
|
||||
allErrors: allErrors
|
||||
};
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
//act
|
||||
serverValidationManager.addFieldError("Name", "Required");
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1", null);
|
||||
@@ -348,7 +505,9 @@
|
||||
var cb2 = function () {
|
||||
};
|
||||
serverValidationManager.subscribe(null, null, "Name", cb1, null);
|
||||
|
||||
serverValidationManager.subscribe(null, null, "Title", cb2, null);
|
||||
|
||||
|
||||
//act
|
||||
serverValidationManager.addFieldError("Name", "Required");
|
||||
@@ -374,6 +533,7 @@
|
||||
var args1;
|
||||
var args2;
|
||||
var numCalled = 0;
|
||||
var numCalledWithErrors = 0;
|
||||
|
||||
//arrange
|
||||
serverValidationManager.subscribe("myProperty", null, "value1", function (isValid, propertyErrors, allErrors) {
|
||||
@@ -384,15 +544,19 @@
|
||||
};
|
||||
}, null);
|
||||
|
||||
|
||||
serverValidationManager.subscribe("myProperty", null, "", function (isValid, propertyErrors, allErrors) {
|
||||
numCalled++;
|
||||
if (propertyErrors.length > 0) {
|
||||
numCalledWithErrors++;
|
||||
}
|
||||
args2 = {
|
||||
isValid: isValid,
|
||||
propertyErrors: propertyErrors,
|
||||
allErrors: allErrors
|
||||
};
|
||||
}, null);
|
||||
|
||||
|
||||
//act
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1", null);
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value2", "Some value 2", null);
|
||||
@@ -415,28 +579,36 @@
|
||||
expect(args2.propertyErrors[0].errorMsg).toEqual("Some value 1");
|
||||
expect(args2.propertyErrors[1].errorMsg).toEqual("Some value 2");
|
||||
expect(args2.allErrors.length).toEqual(2);
|
||||
//Even though only 2 errors are added, the callback is called 3 times because any call to addPropertyError will invoke the callback
|
||||
// if the property has errors existing.
|
||||
expect(numCalled).toEqual(3);
|
||||
//3 errors are added but a call to subscribe also calls the callback
|
||||
expect(numCalled).toEqual(4);
|
||||
expect(numCalledWithErrors).toEqual(3);
|
||||
});
|
||||
|
||||
it('can subscribe to a culture error for both a property and its sub field', function () {
|
||||
var args1;
|
||||
var args2;
|
||||
var numCalled = 0;
|
||||
var numCalledWithErrors = 0;
|
||||
|
||||
//arrange
|
||||
serverValidationManager.subscribe(null, "en-US", null, function (isValid, propertyErrors, allErrors) {
|
||||
numCalled++;
|
||||
if (propertyErrors.length > 0) {
|
||||
numCalledWithErrors++;
|
||||
}
|
||||
args1 = {
|
||||
isValid: isValid,
|
||||
propertyErrors: propertyErrors,
|
||||
allErrors: allErrors
|
||||
};
|
||||
}, null);
|
||||
|
||||
|
||||
serverValidationManager.subscribe(null, "es-ES", null, function (isValid, propertyErrors, allErrors) {
|
||||
numCalled++;
|
||||
if (propertyErrors.length > 0) {
|
||||
numCalledWithErrors++;
|
||||
}
|
||||
args2 = {
|
||||
isValid: isValid,
|
||||
propertyErrors: propertyErrors,
|
||||
@@ -445,20 +617,162 @@
|
||||
}, null);
|
||||
|
||||
//act
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1", null);
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", "value1", "Some value 1", null);
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", "value2", "Some value 2", null);
|
||||
serverValidationManager.addPropertyError("myProperty", "fr-FR", "", "Some value 3", null);
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1", null); // doesn't match
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", "value1", "Some value 1", null); // matches callback 1
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", "value2", "Some value 2", null); // matches callback 1
|
||||
serverValidationManager.addPropertyError("myProperty", "fr-FR", "", "Some value 3", null); // doesn't match - but all callbacks still execute
|
||||
|
||||
//assert
|
||||
expect(args1).not.toBeUndefined();
|
||||
expect(args1.isValid).toBe(false);
|
||||
expect(args2.isValid).toBe(true); // no errors registered for this callback
|
||||
|
||||
expect(args2).toBeUndefined();
|
||||
|
||||
expect(numCalled).toEqual(2);
|
||||
expect(numCalled).toEqual(10); // both subscriptions will be called once per addPropertyError and also called on subscribe
|
||||
expect(numCalledWithErrors).toEqual(3); // the first subscription is called 3 times with errors because the 4th time we call addPropertyError all callbacks still execute
|
||||
});
|
||||
|
||||
|
||||
it('can subscribe to a property validation path prefix', function () {
|
||||
var callbackA = [];
|
||||
var callbackB = [];
|
||||
|
||||
//arrange
|
||||
serverValidationManager.subscribe("myProperty", null, null, function (isValid, propertyErrors, allErrors) {
|
||||
if (propertyErrors.length > 0) {
|
||||
callbackA.push(propertyErrors);
|
||||
}
|
||||
}, null, { matchType: "prefix" });
|
||||
|
||||
serverValidationManager.subscribe("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses", null, null, function (isValid, propertyErrors, allErrors) {
|
||||
if (propertyErrors.length > 0) {
|
||||
callbackB.push(propertyErrors);
|
||||
}
|
||||
}, null, { matchType: "prefix" });
|
||||
|
||||
//act
|
||||
// will match A:
|
||||
serverValidationManager.addPropertyError("myProperty", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "value error", null);
|
||||
// will match A + B
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, "value1", "value error", null);
|
||||
// won't match:
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, "value1", "value error", null);
|
||||
|
||||
//assert
|
||||
|
||||
// both will be called each time addPropertyError is called
|
||||
expect(callbackA.length).toEqual(8);
|
||||
expect(callbackB.length).toEqual(6); // B - will only be called 6 times with errors because the first 2 calls to addPropertyError haven't added errors for B yet
|
||||
expect(callbackA[callbackA.length - 1].length).toEqual(4); // 4 errors for A
|
||||
expect(callbackB[callbackB.length - 1].length).toEqual(2); // 2 errors for B
|
||||
|
||||
// clear the data and notify
|
||||
callbackA = [];
|
||||
callbackB = [];
|
||||
|
||||
serverValidationManager.notify();
|
||||
$timeout.flush();
|
||||
|
||||
expect(callbackA.length).toEqual(1);
|
||||
expect(callbackB.length).toEqual(1);
|
||||
expect(callbackA[0].length).toEqual(4); // 4 errors for A
|
||||
expect(callbackB[0].length).toEqual(2); // 2 errors for B
|
||||
|
||||
});
|
||||
|
||||
it('can subscribe to a property validation path suffix', function () {
|
||||
var callbackA = [];
|
||||
var callbackB = [];
|
||||
|
||||
//arrange
|
||||
serverValidationManager.subscribe("myProperty", null, null, function (isValid, propertyErrors, allErrors) {
|
||||
if (propertyErrors.length > 0) {
|
||||
callbackA.push(propertyErrors);
|
||||
}
|
||||
}, null, { matchType: "suffix" });
|
||||
|
||||
serverValidationManager.subscribe("city", null, null, function (isValid, propertyErrors, allErrors) {
|
||||
if (propertyErrors.length > 0) {
|
||||
callbackB.push(propertyErrors);
|
||||
}
|
||||
}, null, { matchType: "suffix" });
|
||||
|
||||
//act
|
||||
// will match A:
|
||||
serverValidationManager.addPropertyError("myProperty", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty", null, "value1", "value error", null);
|
||||
// will match B
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, "value1", "value error", null);
|
||||
// won't match:
|
||||
serverValidationManager.addPropertyError("myProperty", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, "value1", "value error", null);
|
||||
|
||||
//assert
|
||||
|
||||
// both will be called each time addPropertyError is called
|
||||
expect(callbackA.length).toEqual(8);
|
||||
expect(callbackB.length).toEqual(6); // B - will only be called 6 times with errors because the first 2 calls to addPropertyError haven't added errors for B yet
|
||||
expect(callbackA[callbackA.length - 1].length).toEqual(2); // 2 errors for A
|
||||
expect(callbackB[callbackB.length - 1].length).toEqual(2); // 2 errors for B
|
||||
|
||||
// clear the data and notify
|
||||
callbackA = [];
|
||||
callbackB = [];
|
||||
|
||||
serverValidationManager.notify();
|
||||
$timeout.flush();
|
||||
|
||||
expect(callbackA.length).toEqual(1);
|
||||
expect(callbackB.length).toEqual(1);
|
||||
expect(callbackA[0].length).toEqual(2); // 2 errors for A
|
||||
expect(callbackB[0].length).toEqual(2); // 2 errors for B
|
||||
|
||||
});
|
||||
|
||||
it('can subscribe to a property validation path contains', function () {
|
||||
var callbackA = [];
|
||||
|
||||
//arrange
|
||||
serverValidationManager.subscribe("addresses", null, null, function (isValid, propertyErrors, allErrors) {
|
||||
if (propertyErrors.length > 0) {
|
||||
callbackA.push(propertyErrors);
|
||||
}
|
||||
}, null, { matchType: "contains" });
|
||||
|
||||
//act
|
||||
// will match A:
|
||||
serverValidationManager.addPropertyError("addresses", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("addresses", null, "value1", "value error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("myProperty/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", null, "value1", "value error", null);
|
||||
// won't match:
|
||||
serverValidationManager.addPropertyError("addresses", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("addresses/34E3A26C-103D-4A05-AB9D-7E14032309C3/addresses/FBEAEE8F-4BC9-43EE-8B81-FCA8978850F1/city", "en-US", null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, null, "property error", null);
|
||||
serverValidationManager.addPropertyError("otherProperty", null, "value1", "value error", null);
|
||||
|
||||
//assert
|
||||
|
||||
// both will be called each time addPropertyError is called
|
||||
expect(callbackA.length).toEqual(8);
|
||||
expect(callbackA[callbackA.length - 1].length).toEqual(4); // 4 errors for A
|
||||
|
||||
// clear the data and notify
|
||||
callbackA = [];
|
||||
|
||||
serverValidationManager.notify();
|
||||
$timeout.flush();
|
||||
|
||||
expect(callbackA.length).toEqual(1);
|
||||
expect(callbackA[0].length).toEqual(4); // 4 errors for A
|
||||
|
||||
});
|
||||
|
||||
// TODO: Finish testing the rest!
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user