diff --git a/.github/workflows/common_check.yml b/.github/workflows/common_check.yml
index ca35c1c212..1d44068775 100644
--- a/.github/workflows/common_check.yml
+++ b/.github/workflows/common_check.yml
@@ -43,6 +43,7 @@ jobs:
node-qunit-puppeteer tests/cell/spreadsheet-calculation/FormulaTrace.html
node-qunit-puppeteer tests/cell/spreadsheet-calculation/GoalSeekTests.html
node-qunit-puppeteer tests/cell/spreadsheet-calculation/NumFormatParse.html
+ node-qunit-puppeteer tests/cell/spreadsheet-calculation/DataValidationTests.html
node-qunit-puppeteer tests/word/unit-tests/paragraphContentPos.html
node-qunit-puppeteer tests/word/content-control/block-level/cursorAndSelection.html
node-qunit-puppeteer tests/word/content-control/inline-level/cursorAndSelection.html
diff --git a/.github/workflows/dev_check.yml b/.github/workflows/dev_check.yml
index fdc9799e1f..c1e11db6dc 100644
--- a/.github/workflows/dev_check.yml
+++ b/.github/workflows/dev_check.yml
@@ -43,6 +43,7 @@ jobs:
node-qunit-puppeteer tests/cell/spreadsheet-calculation/FormulaTrace.html
node-qunit-puppeteer tests/cell/spreadsheet-calculation/GoalSeekTests.html
node-qunit-puppeteer tests/cell/spreadsheet-calculation/NumFormatParse.html
+ node-qunit-puppeteer tests/cell/spreadsheet-calculation/DataValidationTests.html
node-qunit-puppeteer tests/word/unit-tests/paragraphContentPos.html
node-qunit-puppeteer tests/word/content-control/block-level/cursorAndSelection.html
node-qunit-puppeteer tests/word/content-control/inline-level/cursorAndSelection.html
diff --git a/tests/cell/spreadsheet-calculation/DataValidationTests.html b/tests/cell/spreadsheet-calculation/DataValidationTests.html
new file mode 100644
index 0000000000..288f1346dc
--- /dev/null
+++ b/tests/cell/spreadsheet-calculation/DataValidationTests.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ Unit Tests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test markup, will be hidden
+
+
+
diff --git a/tests/cell/spreadsheet-calculation/DataValidationTests.js b/tests/cell/spreadsheet-calculation/DataValidationTests.js
new file mode 100644
index 0000000000..5732f36e9b
--- /dev/null
+++ b/tests/cell/spreadsheet-calculation/DataValidationTests.js
@@ -0,0 +1,224 @@
+/*
+ * (c) Copyright Ascensio System SIA 2010-2024
+ *
+ * This program is a free software product. You can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License (AGPL)
+ * version 3 as published by the Free Software Foundation. In accordance with
+ * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
+ * that Ascensio System SIA expressly excludes the warranty of non-infringement
+ * of any third-party rights.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
+ * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
+ *
+ * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
+ * street, Riga, Latvia, EU, LV-1050.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of the Program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU AGPL version 3.
+ *
+ * Pursuant to Section 7(b) of the License you must retain the original Product
+ * logo when distributing the program. Pursuant to Section 7(e) we decline to
+ * grant you any rights under trademark law for use of our trademarks.
+ *
+ * All the Product's GUI elements, including illustrations and icon sets, as
+ * well as technical writing content are licensed under the terms of the
+ * Creative Commons Attribution-ShareAlike 4.0 International. See the License
+ * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
+ *
+ */
+
+$(function () {
+
+ Asc.spreadsheet_api.prototype._init = function () {
+ this._loadModules();
+ };
+ Asc.spreadsheet_api.prototype._loadFonts = function (fonts, callback) {
+ callback();
+ };
+ Asc.spreadsheet_api.prototype.onEndLoadFile = function (fonts, callback) {
+ openDocument();
+ };
+ AscCommonExcel.WorkbookView.prototype._calcMaxDigitWidth = function () {
+ };
+ AscCommonExcel.WorkbookView.prototype._init = function () {
+ };
+ AscCommonExcel.WorkbookView.prototype._isLockedUserProtectedRange = function (callback) {
+ callback(true);
+ };
+ AscCommonExcel.WorkbookView.prototype._onWSSelectionChanged = function () {
+ };
+ AscCommonExcel.WorkbookView.prototype.showWorksheet = function () {
+ };
+ AscCommonExcel.WorkbookView.prototype.recalculateDrawingObjects = function () {
+ };
+ AscCommonExcel.WorkbookView.prototype.restoreFocus = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._init = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype.updateRanges = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._autoFitColumnsWidth = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype.cleanSelection = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._drawSelection = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._scrollToRange = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype.draw = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._prepareDrawingObjects = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._initCellsArea = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype.getZoom = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._prepareCellTextMetricsCache = function () {
+ };
+
+ AscCommon.baseEditorsApi.prototype._onEndLoadSdk = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._isLockedCells = function (range, subType, callback) {
+ callback(true);
+ return true;
+ };
+ AscCommonExcel.WorksheetView.prototype._isLockedAll = function (callback) {
+ callback(true);
+ };
+ AscCommonExcel.WorksheetView.prototype._isLockedFrozenPane = function (callback) {
+ callback(true);
+ };
+ AscCommonExcel.WorksheetView.prototype._updateVisibleColsCount = function () {
+ };
+ AscCommonExcel.WorksheetView.prototype._calcActiveCellOffset = function () {
+ };
+
+ AscCommon.baseEditorsApi.prototype._onEndLoadSdk = function () {
+ };
+ Asc.ReadDefTableStyles = function(){};
+
+ function openDocument(){
+ AscCommon.g_oTableId.init();
+ api._onEndLoadSdk();
+ api.isOpenOOXInBrowser = false;
+ api._openDocument(AscCommon.getEmpty());
+ api._openOnClient();
+ }
+
+ var api = new Asc.spreadsheet_api({
+ 'id-view': 'editor_sdk'
+ });
+ api.FontLoader = {
+ LoadDocumentFonts: function() {}
+ };
+ window["Asc"]["editor"] = api;
+ AscCommon.g_oTableId.init();
+ api._onEndLoadSdk();
+ api.isOpenOOXInBrowser = false;
+ api._openDocument(AscCommon.getEmpty());
+ api._openOnClient();
+ api.collaborativeEditing = new AscCommonExcel.CCollaborativeEditing({});
+ api.wb = new AscCommonExcel.WorkbookView(api.wbModel, api.controller, api.handlers, api.HtmlElement,
+ api.topLineEditorElement, api, api.collaborativeEditing, api.fontRenderingMode);
+ var wb = api.wbModel;
+ wb.handlers.add("getSelectionState", function () {
+ return null;
+ });
+ wb.handlers.add("getLockDefNameManagerStatus", function () {
+ return true;
+ });
+ wb.handlers.add("asc_onConfirmAction", function (test1, callback) {
+ callback(true);
+ });
+ api.wb.cellCommentator = new AscCommonExcel.CCellCommentator({
+ model: api.wbModel.aWorksheets[0],
+ collaborativeEditing: null,
+ draw: function() {
+ },
+ handlers: {
+ trigger: function() {
+ return false;
+ }
+ }
+ });
+
+ AscCommonExcel.CCellCommentator.prototype.isLockedComment = function (oComment, callbackFunc) {
+ callbackFunc(true);
+ };
+ AscCommonExcel.CCellCommentator.prototype.drawCommentCells = function () {
+ };
+ AscCommonExcel.CCellCommentator.prototype.ascCvtRatio = function () {
+ };
+
+ var wsView = api.wb.getWorksheet(0);
+ wsView.handlers = api.handlers;
+ wsView.objectRender = new AscFormat.DrawingObjects();
+ var ws = api.wbModel.aWorksheets[0];
+
+ var getRange = function (c1, r1, c2, r2) {
+ return new window["Asc"].Range(c1, r1, c2, r2);
+ };
+ const clearData = function (c1, r1, c2, r2) {
+ ws.autoFilters.deleteAutoFilter(getRange(0,0,0,0));
+ ws.removeRows(r1, r2, false);
+ ws.removeCols(c1, c2);
+ };
+
+ function checkUndoRedo(fBefore, fAfter, desc) {
+ fAfter("after_" + desc);
+ AscCommon.History.Undo();
+ fBefore("undo_" + desc);
+ AscCommon.History.Redo();
+ fAfter("redo_" + desc);
+ AscCommon.History.Undo();
+ }
+
+ function compareData (assert, range, data, desc) {
+ for (let i = range.r1; i <= range.r2; i++) {
+ for (let j = range.c1; j <= range.c2; j++) {
+ let rangeVal = ws.getCell3(i, j);
+ let dataVal = data[i - range.r1][j - range.c1];
+ assert.strictEqual(rangeVal.getValue(), dataVal, desc + " compare " + rangeVal.getName());
+ }
+ }
+ }
+
+ QUnit.test('Data validation: custom formula manipulation', function (assert) {
+
+ assert.strictEqual(ws.dataValidations, null, "Data validation count before add");
+
+ const props = new AscCommonExcel.CDataValidation();
+ props.asc_setType(Asc.EDataValidationType.Custom);
+ props.setShowErrorMessage(true);
+ props.asc_setFormula1(new Asc.CDataFormula('=COUNTIF(B:B;B1)=1'));
+
+ wsView.setSelection(new Asc.Range(1, 0, 1, AscCommon.gc_nMaxRow0));
+ api.asc_setDataValidation(props);
+
+
+ assert.strictEqual(ws.dataValidations.elems.length, 1, "Data validation count after add");
+ assert.strictEqual(ws.getDataValidation(0, 0), null, "Check data validation in A1");
+ assert.strictEqual(!!(ws.getDataValidation(1, 0)), true, "Check data validation in B1");
+
+ //try to add value
+ let oDataValidation = ws.getDataValidation(1, 0);
+
+ //imitate try to set value into B1
+ ws.getRange2("B1").setValue("test1");
+ wsView.setSelection(new Asc.Range(1, 0, 1, 0));
+ assert.strictEqual(oDataValidation.checkValue(new AscCommonExcel.Cell(), ws), true, "B4 validation before add repeated values");
+
+ //imitate try to set value into B2
+ ws.getRange2("B2").setValue("test1");
+
+ wsView.setSelection(new Asc.Range(1, 1, 1, 1));
+ assert.strictEqual(oDataValidation.checkValue(new AscCommonExcel.Cell(), ws), false, "B4 validation before add repeated values");
+
+ //clearData(0, 6, 0, 6);
+ });
+
+ QUnit.module("Sheet structure");
+});