function test(iExpectedResult, sProperty) {
			var oNewColumn = {},
				aNewColumns = [{}, oNewColumn],
				oOldColumn = {},
				aOldColumns = [{}, oOldColumn];

			oNewColumn[sProperty] = "new";
			oOldColumn[sProperty] = "old";
			if (iExpectedResult === 2) { // important changes win
				aNewColumns.unshift({formatter : "new"});
				aOldColumns.unshift({formatter : "old"});
			}

			// code under test
			assert.strictEqual(
				odata4analytics.helper.deepEqual(aOldColumns, aNewColumns),
				iExpectedResult);
		}
******************************************************************************************
	QUnit.test("_renderPropertyFilterValue", function (assert) {
		const oDataUtilsMock = sinon.mock(ODataUtils);
		oDataUtilsMock.expects("_formatValue")
			.withExactArgs("~sFilterValue", "~sPropertyEDMTypeName", true, "~sFractionalSeconds")
			.returns("~unecoded Value");

		// code under test
		assert.strictEqual(new odata4analytics.FilterExpression()._renderPropertyFilterValue("~sFilterValue",
			"~sPropertyEDMTypeName", "~sFractionalSeconds"), "%7eunecoded%20Value");

		oDataUtilsMock.verify();
	});

	//*********************************************************************************************
	QUnit.test("_renderPropertyFilterValue, Edm.Time", function (assert) {
		const oDataUtilsMock = sinon.mock(ODataUtils);
		oDataUtilsMock.expects("_formatValue")
			.withExactArgs({ms : 42, __edmType : "Edm.Time"}, "Edm.Time", true, "~sFractionalSeconds")
			.returns("~unecoded Value");

		// code under test
		assert.strictEqual(new odata4analytics.FilterExpression()._renderPropertyFilterValue("42", "Edm.Time",
			"~sFractionalSeconds"), "%7eunecoded%20Value");

		oDataUtilsMock.verify();
	});

	//*********************************************************************************************
	QUnit.test("_renderPropertyFilterValue, Edm.Time but not only digits", function (assert) {
		const oDataUtilsMock = sinon.mock(ODataUtils);
		oDataUtilsMock.expects("_formatValue")
			.withExactArgs("42notOnlyDigits", "Edm.Time", true, "~sFractionalSeconds")
			.returns("~unecoded Value");

		// code under test
		assert.strictEqual(new odata4analytics.FilterExpression()._renderPropertyFilterValue("42notOnlyDigits",
			"Edm.Time", "~sFractionalSeconds"), "%7eunecoded%20Value");

		oDataUtilsMock.verify();
	});

	//*********************************************************************************************
[
	{sOperator: FilterOperator.BT, sExpectedResult: "(~sPath ge ~renderedValue1 and ~sPath le ~renderedValue2)"},
	{sOperator: FilterOperator.NB, sExpectedResult: "(~sPath lt ~renderedValue1 or ~sPath gt ~renderedValue2)"},
	{sOperator: FilterOperator.Contains, sExpectedResult: "substringof(~renderedValue1,~sPath)"},
	{sOperator: FilterOperator.NotContains, sExpectedResult: "not substringof(~renderedValue1,~sPath)"},
	{sOperator: FilterOperator.StartsWith, sExpectedResult: "startswith(~sPath,~renderedValue1)"},
	{sOperator: FilterOperator.EndsWith, sExpectedResult: "endswith(~sPath,~renderedValue1)"},
	{sOperator: FilterOperator.NotStartsWith, sExpectedResult: "not startswith(~sPath,~renderedValue1)"},
	{sOperator: FilterOperator.NotEndsWith, sExpectedResult: "not endswith(~sPath,~renderedValue1)"},
	{sOperator: "OtherOperator", sExpectedResult: "~sPath otheroperator ~renderedValue1"}
].forEach((oFixture) => {
	QUnit.test("renderUI5Filter: " + oFixture.sOperator, function (assert) {
		const oFilter = {
			sPath: "~sPath",
			sOperator : oFixture.sOperator,
			oValue1 : "~sValue1",
			oValue2 : "~sValue2",
			sFractionalSeconds1 : "~sFractionalSeconds1",
			sFractionalSeconds2 : "~sFractionalSeconds1"
		};
		const oProperty = {type : "~sEDMTypeName"};
		const oEntityType = {findPropertyByName : function () {}};
		const oFilterExpression = new odata4analytics.FilterExpression(undefined, undefined, oEntityType);
		const oFilterExpressionMock = sinon.mock(oFilterExpression);
		const oEntityMock = sinon.mock(oFilterExpression._oEntityType);
		oEntityMock.expects("findPropertyByName").withExactArgs(oFilter.sPath).returns(oProperty);
		const aStringOperators = [FilterOperator.Contains, FilterOperator.NotContains, FilterOperator.StartsWith,
			FilterOperator.EndsWith, FilterOperator.NotStartsWith, FilterOperator.NotEndsWith];
		if (aStringOperators.includes(oFixture.sOperator)) {
			oFilterExpressionMock.expects("_renderPropertyFilterValue")
				.withExactArgs(oFilter.oValue1, "Edm.String")
				.returns("~renderedValue1");
		} else {
			oFilterExpressionMock.expects("_renderPropertyFilterValue")
				.withExactArgs(oFilter.oValue1, oProperty.type, oFilter.sFractionalSeconds1)
				.returns("~renderedValue1");
		}
		if ([FilterOperator.BT, FilterOperator.NB].includes(oFixture.sOperator)) {
			oFilterExpressionMock.expects("_renderPropertyFilterValue")
				.withExactArgs(oFilter.oValue2, oProperty.type, oFilter.sFractionalSeconds2)
				.returns("~renderedValue2");
		}

		// code under test
		assert.strictEqual(oFilterExpression.renderUI5Filter(oFilter), oFixture.sExpectedResult);

		oEntityMock.verify();
		oFilterExpressionMock.verify();
	});
});

	//*********************************************************************************************
	QUnit.test("renderUI5Filter: fails", function (assert) {
		const oEntityType = {findPropertyByName : function () {}};
		const oFilterExpression = new odata4analytics.FilterExpression(undefined, undefined, oEntityType);
		const oEntityMock = sinon.mock(oFilterExpression._oEntityType);
		oEntityMock.expects("findPropertyByName").withExactArgs("~sPath").returns(null);

		// code under test
		assert.throws(function () {
			oFilterExpression.renderUI5Filter({sPath: "~sPath"});
		}, /Cannot add filter condition for unknown property name ~sPath/);

		oEntityMock.verify();
	});

	//*********************************************************************************************
	// BCP: 985176/2023
	QUnit.test("renderUI5FilterArray", function (assert) {
		const aFilterArray = [
			{sPath: 'Material'},
			{aFilters: [/*Multi Filter