From 11f1250d739c8f551d19164c479f2e43a299d2d2 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Thu, 18 Apr 2024 20:48:26 -0500 Subject: [PATCH] the missing selenium test for the report setup screen from last sprint --- .../selenium/lib/QueryScreenLib.java | 19 +- .../selenium/tests/SavedReportTest.java | 172 ++++++++++++++ .../selenium/tests/query/QueryScreenTest.java | 12 +- .../savedReport/possibleValues/tableName.json | 16 ++ .../resources/fixtures/metaData/index.json | 90 ++++++++ .../fixtures/metaData/table/savedReport.json | 218 ++++++++++++++++++ .../widget/pivotTableSetupWidget.json | 1 + .../fixtures/widget/reportSetupWidget.json | 1 + 8 files changed, 520 insertions(+), 9 deletions(-) create mode 100755 src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/SavedReportTest.java create mode 100644 src/test/resources/fixtures/data/savedReport/possibleValues/tableName.json create mode 100644 src/test/resources/fixtures/metaData/table/savedReport.json create mode 100644 src/test/resources/fixtures/widget/pivotTableSetupWidget.json create mode 100644 src/test/resources/fixtures/widget/reportSetupWidget.json diff --git a/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/lib/QueryScreenLib.java b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/lib/QueryScreenLib.java index d355f38..fe6d2fb 100644 --- a/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/lib/QueryScreenLib.java +++ b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/lib/QueryScreenLib.java @@ -261,9 +261,7 @@ public class QueryScreenLib if(StringUtils.hasContent(value)) { qSeleniumLib.waitForSelector(".filterValuesColumn INPUT").click(); - // todo - no, not in a listbox/LI here... - qSeleniumLib.waitForSelectorContaining(".MuiAutocomplete-listbox LI", value).click(); - System.out.println(value); + qSeleniumLib.waitForSelector(".filterValuesColumn INPUT").sendKeys(value); } qSeleniumLib.clickBackdrop(); @@ -271,6 +269,21 @@ public class QueryScreenLib + /******************************************************************************* + ** + *******************************************************************************/ + public void setBasicBooleanFilter(String fieldLabel, String operatorLabel) + { + qSeleniumLib.waitForSelectorContaining("BUTTON", fieldLabel).click(); + qSeleniumLib.waitForMillis(250); + qSeleniumLib.waitForSelector("#criteriaOperator").click(); + qSeleniumLib.waitForSelectorContaining("LI", operatorLabel).click(); + + qSeleniumLib.clickBackdrop(); + } + + + /******************************************************************************* ** *******************************************************************************/ diff --git a/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/SavedReportTest.java b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/SavedReportTest.java new file mode 100755 index 0000000..4d493c3 --- /dev/null +++ b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/SavedReportTest.java @@ -0,0 +1,172 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * 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 . + */ + +package com.kingsrook.qqq.frontend.materialdashboard.selenium.tests; + + +import java.util.List; +import com.kingsrook.qqq.frontend.materialdashboard.selenium.lib.QBaseSeleniumTest; +import com.kingsrook.qqq.frontend.materialdashboard.selenium.lib.QSeleniumLib; +import com.kingsrook.qqq.frontend.materialdashboard.selenium.lib.QueryScreenLib; +import com.kingsrook.qqq.frontend.materialdashboard.selenium.lib.javalin.QSeleniumJavalin; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + + +/******************************************************************************* + ** Test for Saved Report screen (table has some special behaviors) + *******************************************************************************/ +public class SavedReportTest extends QBaseSeleniumTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + protected void addJavalinRoutes(QSeleniumJavalin qSeleniumJavalin) + { + super.addJavalinRoutes(qSeleniumJavalin); + qSeleniumJavalin + .withRouteToFile("/metaData/table/savedReport", "metaData/table/savedReport.json") + .withRouteToFile("/widget/reportSetupWidget", "widget/reportSetupWidget.json") + .withRouteToFile("/widget/pivotTableSetupWidget", "widget/pivotTableSetupWidget.json") + .withRouteToFile("/data/savedReport/possibleValues/tableName", "data/savedReport/possibleValues/tableName.json") + + .withRouteToFile("/data/person/count", "data/person/count.json") + .withRouteToFile("/data/person/query", "data/person/index.json") + ; + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testCreate() + { + qSeleniumLib.gotoAndWaitForBreadcrumbHeaderToContain("/userCustomizations/savedReport/create", "Creating New Saved Report"); + + ////////////////////////////////////////////////////////////// + // make sure things are disabled before a table is selected // + ////////////////////////////////////////////////////////////// + WebElement webElement = qSeleniumLib.waitForSelectorContaining("button", "Edit Filters and Columns"); + assertEquals("true", webElement.getAttribute("disabled")); + + qSeleniumLib.waitForSelector("#label").click(); + qSeleniumLib.waitForSelector("#label").sendKeys("My Report"); + + qSeleniumLib.waitForSelector("#tableName").click(); + qSeleniumLib.waitForSelector("#tableName").sendKeys("Person" + Keys.DOWN + Keys.ENTER); + + ////////////////////////////////// + // make sure things enabled now // + ////////////////////////////////// + webElement = qSeleniumLib.waitForSelectorContaining("button", "Edit Filters and Columns"); + assertNull(webElement.getAttribute("disabled")); + + //////////////////////////////////////////////////// + // open query-screen popup, wait for query to run // + //////////////////////////////////////////////////// + qSeleniumJavalin.beginCapture(); + qSeleniumLib.waitForSelectorContaining("button", "Edit Filters and Columns").click(); + qSeleniumJavalin.waitForCapturedPath("/data/person/count"); + qSeleniumJavalin.waitForCapturedPath("/data/person/query"); + qSeleniumJavalin.endCapture(); + + QueryScreenLib queryScreenLib = new QueryScreenLib(qSeleniumLib); + queryScreenLib.setBasicFilter("First Name", "contains", "Darin"); + + //////////////////////// + // close query screen // + //////////////////////// + qSeleniumLib.waitForSelectorContaining("button", "OK").click(); + + ////////////////////////////////////////////////////// + // make sure query things appear on edit screen now // + ////////////////////////////////////////////////////// + qSeleniumLib.waitForSelectorContaining(".advancedQueryString", "First Name"); + qSeleniumLib.waitForSelectorContaining(".advancedQueryString", "contains"); + qSeleniumLib.waitForSelectorContaining(".advancedQueryString", "Darin"); + List columns = qSeleniumLib.waitForSelectorContaining("h5", "Columns") + .findElement(QSeleniumLib.PARENT) + .findElements(By.cssSelector("DIV")); + + assertThat(columns) + .hasSizeGreaterThanOrEqualTo(5) // at least this many + .anyMatch(we -> we.getText().equals("Home City")); // a few fields are found + + /////////////////// + // turn on pivot // + /////////////////// + qSeleniumLib.waitForSelectorContaining("label", "Use Pivot Table").click(); + qSeleniumLib.waitForSelectorContaining("button", "Edit Pivot Table").click(); + qSeleniumLib.waitForSelectorContaining("h3", "Edit Pivot Table"); + + /////////////// + // add a row // + /////////////// + qSeleniumLib.waitForSelectorContaining(".MuiModal-root button", "Add new row").click(); + WebElement row0Input = qSeleniumLib.waitForSelector("#rows-0"); + row0Input.click(); + row0Input.sendKeys("Last Name" + Keys.ENTER); + + ////////////////// + // add a column // + ////////////////// + qSeleniumLib.waitForSelectorContaining(".MuiModal-root button", "Add new column").click(); + WebElement column0Input = qSeleniumLib.waitForSelector("#columns-0"); + column0Input.click(); + column0Input.sendKeys("Home City" + Keys.ENTER); + + ///////////////// + // add a value // + ///////////////// + qSeleniumLib.waitForSelectorContaining(".MuiModal-root button", "Add new value").click(); + WebElement value0Input = qSeleniumLib.waitForSelector("#values-field-0"); + value0Input.click(); + value0Input.sendKeys("Id" + Keys.ENTER); + + ///////////////////////////////////////// + // try to submit - but expect an error // + ///////////////////////////////////////// + qSeleniumLib.waitForSelectorContaining("button", "OK").click(); + qSeleniumLib.waitForSelectorContaining(".MuiAlert-standard", "Missing value in 1 field.").click(); + + /////////////////////////// + // now select a function // + /////////////////////////// + WebElement function0Input = qSeleniumLib.waitForSelector("#values-function-0"); + function0Input.click(); + function0Input.sendKeys("Count" + Keys.ENTER); + + qSeleniumLib.waitForSelectorContaining("button", "OK").click(); + qSeleniumLib.waitForSelectorContainingToNotExist("h3", "Edit Pivot Table"); + + // qSeleniumLib.waitForever(); + } + +} diff --git a/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/query/QueryScreenTest.java b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/query/QueryScreenTest.java index 3dbf608..0cb7ce4 100755 --- a/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/query/QueryScreenTest.java +++ b/src/test/java/com/kingsrook/qqq/frontend/materialdashboard/selenium/tests/query/QueryScreenTest.java @@ -153,16 +153,16 @@ public class QueryScreenTest extends QBaseSeleniumTest queryScreenLib.addBasicFilter("Is Employed"); - testBasicCriteria(queryScreenLib, "Is Employed", "equals yes", null, "(?s).*Is Employed:.*yes.*", """ + testBasicBooleanCriteria(queryScreenLib, "Is Employed", "equals yes", "(?s).*Is Employed:.*yes.*", """ {"fieldName":"isEmployed","operator":"EQUALS","values":[true]}"""); - testBasicCriteria(queryScreenLib, "Is Employed", "equals no", null, "(?s).*Is Employed:.*no.*", """ + testBasicBooleanCriteria(queryScreenLib, "Is Employed", "equals no", "(?s).*Is Employed:.*no.*", """ {"fieldName":"isEmployed","operator":"EQUALS","values":[false]}"""); - testBasicCriteria(queryScreenLib, "Is Employed", "is empty", null, "(?s).*Is Employed:.*is empty.*", """ + testBasicBooleanCriteria(queryScreenLib, "Is Employed", "is empty", "(?s).*Is Employed:.*is empty.*", """ {"fieldName":"isEmployed","operator":"IS_BLANK","values":[]}"""); - testBasicCriteria(queryScreenLib, "Is Employed", "is not empty", null, "(?s).*Is Employed:.*is not empty.*", """ + testBasicBooleanCriteria(queryScreenLib, "Is Employed", "is not empty", "(?s).*Is Employed:.*is not empty.*", """ {"fieldName":"isEmployed","operator":"IS_NOT_BLANK","values":[]}"""); } @@ -203,10 +203,10 @@ public class QueryScreenTest extends QBaseSeleniumTest /******************************************************************************* ** *******************************************************************************/ - private void testBasicCriteria(QueryScreenLib queryScreenLib, String fieldLabel, String operatorLabel, String value, String expectButtonStringRegex, String expectFilterJsonContains) + private void testBasicBooleanCriteria(QueryScreenLib queryScreenLib, String fieldLabel, String operatorLabel, String expectButtonStringRegex, String expectFilterJsonContains) { qSeleniumJavalin.beginCapture(); - queryScreenLib.setBasicFilter(fieldLabel, operatorLabel, value); + queryScreenLib.setBasicBooleanFilter(fieldLabel, operatorLabel); queryScreenLib.waitForBasicFilterButtonMatchingRegex(expectButtonStringRegex); qSeleniumJavalin.waitForCapturedPathWithBodyContaining("/data/person/query", expectFilterJsonContains); qSeleniumJavalin.endCapture(); diff --git a/src/test/resources/fixtures/data/savedReport/possibleValues/tableName.json b/src/test/resources/fixtures/data/savedReport/possibleValues/tableName.json new file mode 100644 index 0000000..2f642c6 --- /dev/null +++ b/src/test/resources/fixtures/data/savedReport/possibleValues/tableName.json @@ -0,0 +1,16 @@ +{ + "options": [ + { + "id": "person", + "label": "Person" + }, + { + "id": "city", + "label": "City" + }, + { + "id": "savedReport", + "label": "Saved Report" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/fixtures/metaData/index.json b/src/test/resources/fixtures/metaData/index.json index 9fb571f..401fcda 100644 --- a/src/test/resources/fixtures/metaData/index.json +++ b/src/test/resources/fixtures/metaData/index.json @@ -189,6 +189,26 @@ "insertPermission": true, "editPermission": true, "deletePermission": true + }, + "savedReport": { + "name": "savedReport", + "label": "Saved Report", + "isHidden": false, + "iconName": "article", + "capabilities": [ + "TABLE_COUNT", + "TABLE_GET", + "TABLE_QUERY", + "QUERY_STATS", + "TABLE_UPDATE", + "TABLE_INSERT", + "TABLE_DELETE" + ], + "readPermission": true, + "insertPermission": true, + "editPermission": true, + "deletePermission": true, + "usesVariants": false } }, "processes": { @@ -420,6 +440,40 @@ } ] }, + "userCustomizations": { + "name": "userCustomizations", + "label": "User Customizations", + "iconName": "article", + "widgets": [], + "children": [ + { + "type": "TABLE", + "name": "savedReport", + "label": "Saved Report", + "iconName": "article" + } + ], + "childMap": { + "savedReport": { + "type": "TABLE", + "name": "savedReport", + "label": "Saved Report", + "iconName": "article" + } + }, + "sections": [ + { + "name": "userCustomizations", + "label": "User Customizations", + "icon": { + "name": "badge" + }, + "tables": [ + "savedReport" + ] + } + ] + }, "miscellaneous": { "name": "miscellaneous", "label": "Miscellaneous", @@ -730,6 +784,20 @@ } ], "iconName": "data_object" + }, + { + "type": "APP", + "name": "userCustomizations", + "label": "User Customizations", + "children": [ + { + "type": "TABLE", + "name": "savedReport", + "label": "Saved Report", + "iconName": "article" + } + ], + "iconName": "data_object" } ], "branding": { @@ -750,6 +818,28 @@ "isCard": true, "storeDropdownSelections": false, "hasPermission": true + }, + "reportSetupWidget": { + "name": "reportSetupWidget", + "label": "Filters and Columns", + "type": "reportSetup", + "isCard": true, + "storeDropdownSelections": false, + "showReloadButton": true, + "showExportButton": false, + "defaultValues": {}, + "hasPermission": true + }, + "pivotTableSetupWidget": { + "name": "pivotTableSetupWidget", + "label": "Pivot Table", + "type": "pivotTableSetup", + "isCard": true, + "storeDropdownSelections": false, + "showReloadButton": true, + "showExportButton": false, + "defaultValues": {}, + "hasPermission": true } }, "environmentValues": { diff --git a/src/test/resources/fixtures/metaData/table/savedReport.json b/src/test/resources/fixtures/metaData/table/savedReport.json new file mode 100644 index 0000000..71e256b --- /dev/null +++ b/src/test/resources/fixtures/metaData/table/savedReport.json @@ -0,0 +1,218 @@ +{ + "table": { + "name": "savedReport", + "label": "Saved Report", + "isHidden": false, + "primaryKeyField": "id", + "iconName": "article", + "fields": { + "queryFilterJson": { + "name": "queryFilterJson", + "label": "Query Filter", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "columnsJson": { + "name": "columnsJson", + "label": "Columns", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "inputFieldsJson": { + "name": "inputFieldsJson", + "label": "Input Fields", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "pivotTableJson": { + "name": "pivotTableJson", + "label": "Pivot Table", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "modifyDate": { + "name": "modifyDate", + "label": "Modify Date", + "type": "DATE_TIME", + "isRequired": false, + "isEditable": false, + "isHeavy": false, + "displayFormat": "%s" + }, + "label": { + "name": "label", + "label": "Report Name", + "type": "STRING", + "isRequired": true, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "id": { + "name": "id", + "label": "Id", + "type": "INTEGER", + "isRequired": false, + "isEditable": false, + "isHeavy": false, + "displayFormat": "%s" + }, + "userId": { + "name": "userId", + "label": "User Id", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "tableName": { + "name": "tableName", + "label": "Table", + "type": "STRING", + "isRequired": true, + "isEditable": true, + "isHeavy": false, + "possibleValueSourceName": "tables", + "displayFormat": "%s" + }, + "createDate": { + "name": "createDate", + "label": "Create Date", + "type": "DATE_TIME", + "isRequired": false, + "isEditable": false, + "isHeavy": false, + "displayFormat": "%s" + } + }, + "sections": [ + { + "name": "identity", + "label": "Identity", + "tier": "T1", + "fieldNames": [ + "id", + "label", + "tableName" + ], + "icon": { + "name": "badge" + }, + "isHidden": false + }, + { + "name": "filtersAndColumns", + "label": "Filters and Columns", + "tier": "T2", + "widgetName": "reportSetupWidget", + "icon": { + "name": "table_chart" + }, + "isHidden": false + }, + { + "name": "pivotTable", + "label": "Pivot Table", + "tier": "T2", + "widgetName": "pivotTableSetupWidget", + "icon": { + "name": "pivot_table_chart" + }, + "isHidden": false + }, + { + "name": "data", + "label": "Data", + "tier": "T2", + "fieldNames": [ + "queryFilterJson", + "columnsJson", + "pivotTableJson" + ], + "icon": { + "name": "text_snippet" + }, + "isHidden": true + }, + { + "name": "hidden", + "label": "Hidden", + "tier": "T2", + "fieldNames": [ + "inputFieldsJson", + "userId" + ], + "icon": { + "name": "text_snippet" + }, + "isHidden": true + }, + { + "name": "dates", + "label": "Dates", + "tier": "T3", + "fieldNames": [ + "createDate", + "modifyDate" + ], + "icon": { + "name": "calendar_month" + }, + "isHidden": false + } + ], + "exposedJoins": [], + "supplementalTableMetaData": { + "materialDashboard": { + "fieldRules": [ + { + "trigger": "ON_CHANGE", + "sourceField": "tableName", + "action": "CLEAR_TARGET_FIELD", + "targetField": "queryFilterJson" + }, + { + "trigger": "ON_CHANGE", + "sourceField": "tableName", + "action": "CLEAR_TARGET_FIELD", + "targetField": "columnsJson" + }, + { + "trigger": "ON_CHANGE", + "sourceField": "tableName", + "action": "CLEAR_TARGET_FIELD", + "targetField": "pivotTableJson" + } + ], + "type": "materialDashboard" + } + }, + "capabilities": [ + "TABLE_COUNT", + "TABLE_GET", + "TABLE_QUERY", + "QUERY_STATS", + "TABLE_UPDATE", + "TABLE_INSERT", + "TABLE_DELETE" + ], + "readPermission": true, + "insertPermission": true, + "editPermission": true, + "deletePermission": true, + "usesVariants": false + } +} \ No newline at end of file diff --git a/src/test/resources/fixtures/widget/pivotTableSetupWidget.json b/src/test/resources/fixtures/widget/pivotTableSetupWidget.json new file mode 100644 index 0000000..938d365 --- /dev/null +++ b/src/test/resources/fixtures/widget/pivotTableSetupWidget.json @@ -0,0 +1 @@ +{"type":"pivotTableSetup"} \ No newline at end of file diff --git a/src/test/resources/fixtures/widget/reportSetupWidget.json b/src/test/resources/fixtures/widget/reportSetupWidget.json new file mode 100644 index 0000000..9fa1cb1 --- /dev/null +++ b/src/test/resources/fixtures/widget/reportSetupWidget.json @@ -0,0 +1 @@ +{"type":"reportSetup"} \ No newline at end of file