From 5aac9ce069e346d4d981d98ed3c88f7afb1141b4 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Thu, 17 Aug 2023 16:13:50 -0500 Subject: [PATCH 1/5] hotfix: fixed bug where navigating from one record to another, then hitting the 'e' button goes to the edit screen for the previous record --- src/qqq/pages/records/view/RecordView.tsx | 2 +- .../lib/QBaseSeleniumTest.java | 2 + ...ClickLinkOnRecordThenEditShortcutTest.java | 63 ++++++++ .../fixtures/data/scriptRevision/100.json | 31 ++-- .../resources/fixtures/metaData/index.json | 3 +- .../metaData/table/scriptRevision.json | 152 ++++++++++++++++++ 6 files changed, 231 insertions(+), 22 deletions(-) create mode 100755 src/test/java/com/kingsrook/qqq/materialdashboard/tests/ClickLinkOnRecordThenEditShortcutTest.java create mode 100644 src/test/resources/fixtures/metaData/table/scriptRevision.json diff --git a/src/qqq/pages/records/view/RecordView.tsx b/src/qqq/pages/records/view/RecordView.tsx index c9124e2..b7e4727 100644 --- a/src/qqq/pages/records/view/RecordView.tsx +++ b/src/qqq/pages/records/view/RecordView.tsx @@ -193,7 +193,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element { document.removeEventListener("keydown", down) } - }, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData]) + }, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData, location]) const gotoCreate = () => { diff --git a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java index 8f3ece1..cf1a7b9 100755 --- a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java +++ b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java @@ -75,6 +75,8 @@ public class QBaseSeleniumTest .withRouteToFile("/metaData/authentication", "metaData/authentication.json") .withRouteToFile("/metaData/table/person", "metaData/table/person.json") .withRouteToFile("/metaData/table/city", "metaData/table/person.json") + .withRouteToFile("/metaData/table/script", "metaData/table/script.json") + .withRouteToFile("/metaData/table/scriptRevision", "metaData/table/scriptRevision.json") .withRouteToFile("/processes/querySavedFilter/init", "processes/querySavedFilter/init.json"); } diff --git a/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ClickLinkOnRecordThenEditShortcutTest.java b/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ClickLinkOnRecordThenEditShortcutTest.java new file mode 100755 index 0000000..25ca3c9 --- /dev/null +++ b/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ClickLinkOnRecordThenEditShortcutTest.java @@ -0,0 +1,63 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. 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.materialdashboard.tests; + + +import com.kingsrook.qqq.materialdashboard.lib.QBaseSeleniumTest; +import com.kingsrook.qqq.materialdashboard.lib.javalin.QSeleniumJavalin; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/******************************************************************************* + ** Test for Associated Record Scripts functionality. + *******************************************************************************/ +public class ClickLinkOnRecordThenEditShortcutTest extends QBaseSeleniumTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + protected void addJavalinRoutes(QSeleniumJavalin qSeleniumJavalin) + { + super.addJavalinRoutes(qSeleniumJavalin); + qSeleniumJavalin.withRouteToFile("/data/script/1", "data/script/1.json"); + qSeleniumJavalin.withRouteToFile("/data/scriptRevision/100", "data/scriptRevision/100.json"); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testClickLinkOnRecordThenEditShortcutTest() + { + qSeleniumLib.gotoAndWaitForBreadcrumbHeader("/developer/script/1", "Hello, Script"); + qSeleniumLib.waitForSelectorContaining("A", "100").click(); + + qSeleniumLib.waitForSelectorContaining("BUTTON", "actions").sendKeys("e"); + assertTrue(qSeleniumLib.driver.getCurrentUrl().endsWith("/scriptRevision/100/edit")); + } + +} diff --git a/src/test/resources/fixtures/data/scriptRevision/100.json b/src/test/resources/fixtures/data/scriptRevision/100.json index 8de0400..35830ef 100644 --- a/src/test/resources/fixtures/data/scriptRevision/100.json +++ b/src/test/resources/fixtures/data/scriptRevision/100.json @@ -1,28 +1,19 @@ { "tableName": "scriptRevision", + "recordLabel": "Hello, Script Revision", "values": { - "id": 100, - "commitMessage": "Initial checkin", - "author": "Jon Programmer", + "id": "100", + "name": "Hello, Script Revision", + "sequenceNo": "22", "createDate": "2023-02-18T00:47:51Z", "modifyDate": "2023-02-18T00:47:51Z" }, "displayValues": { - - }, - "associatedRecords": { - "files": [ - { - "tableName": "scriptRevisionFile", - "values": { - "id": 101, - "fileName": "Script.js", - "contents": "var hello;", - "scriptRevisionId": 100, - "createDate": "2023-06-23T21:59:57Z", - "modifyDate": "2023-06-23T21:59:57Z" - } - } - ] + "id": "1", + "name": "Hello, Script Revision", + "scriptId": "1", + "sequenceNo": "22", + "createDate": "2023-02-18T00:47:51Z", + "modifyDate": "2023-02-18T00:47:51Z" } -} \ 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 8bfc77d..af09f14 100644 --- a/src/test/resources/fixtures/metaData/index.json +++ b/src/test/resources/fixtures/metaData/index.json @@ -131,7 +131,8 @@ "capabilities": [ "TABLE_COUNT", "TABLE_GET", - "TABLE_QUERY" + "TABLE_QUERY", + "TABLE_UPDATE" ], "readPermission": true, "insertPermission": true, diff --git a/src/test/resources/fixtures/metaData/table/scriptRevision.json b/src/test/resources/fixtures/metaData/table/scriptRevision.json new file mode 100644 index 0000000..78440da --- /dev/null +++ b/src/test/resources/fixtures/metaData/table/scriptRevision.json @@ -0,0 +1,152 @@ +{ + "table": { + "name": "scriptRevision", + "label": "Script Revision", + "isHidden": false, + "primaryKeyField": "id", + "iconName": "history_edu", + "fields": { + "scriptId": { + "name": "scriptId", + "label": "Script", + "type": "INTEGER", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "possibleValueSourceName": "script", + "displayFormat": "%s", + "adornments": [ + { + "type": "SIZE", + "values": { + "width": "large" + } + }, + { + "type": "LINK", + "values": { + "toRecordFromTable": "script" + } + } + ] + }, + "apiName": { + "name": "apiName", + "label": "API Name", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "possibleValueSourceName": "apiName", + "displayFormat": "%s" + }, + "sequenceNo": { + "name": "sequenceNo", + "label": "Sequence No", + "type": "INTEGER", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "apiVersion": { + "name": "apiVersion", + "label": "API Version", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "possibleValueSourceName": "apiVersion", + "displayFormat": "%s" + }, + "commitMessage": { + "name": "commitMessage", + "label": "Commit Message", + "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" + }, + "author": { + "name": "author", + "label": "Author", + "type": "STRING", + "isRequired": false, + "isEditable": true, + "isHeavy": false, + "displayFormat": "%s" + }, + "id": { + "name": "id", + "label": "Id", + "type": "INTEGER", + "isRequired": false, + "isEditable": false, + "isHeavy": false, + "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", + "scriptId", + "sequenceNo" + ], + "icon": { + "name": "badge" + }, + "isHidden": false + }, + { + "name": "dates", + "label": "Dates", + "tier": "T3", + "fieldNames": [ + "createDate", + "modifyDate" + ], + "icon": { + "name": "calendar_month" + }, + "isHidden": false + } + ], + "exposedJoins": [], + "capabilities": [ + "TABLE_COUNT", + "TABLE_GET", + "TABLE_QUERY", + "TABLE_INSERT", + "TABLE_UPDATE", + "QUERY_STATS" + ], + "readPermission": true, + "insertPermission": true, + "editPermission": true, + "deletePermission": true, + "usesVariants": false + } +} From 19aebd631a8caf645a162ffb7faa862ad19d7c0f Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Thu, 17 Aug 2023 16:48:44 -0500 Subject: [PATCH 2/5] attempt to fix seleniums --- .../tests/ScriptTableTest.java | 2 -- .../fixtures/data/scriptRevision/100.json | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ScriptTableTest.java b/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ScriptTableTest.java index 792ba85..c6d1e2b 100755 --- a/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ScriptTableTest.java +++ b/src/test/java/com/kingsrook/qqq/materialdashboard/tests/ScriptTableTest.java @@ -64,8 +64,6 @@ public class ScriptTableTest extends QBaseSeleniumTest qSeleniumLib.waitForSelectorContaining("DIV.ace_line", "var hello;"); qSeleniumLib.waitForSelectorContaining("DIV", "2nd commit"); qSeleniumLib.waitForSelectorContaining("DIV", "Initial checkin"); - - qSeleniumLib.waitForever(); } } diff --git a/src/test/resources/fixtures/data/scriptRevision/100.json b/src/test/resources/fixtures/data/scriptRevision/100.json index 35830ef..955ab34 100644 --- a/src/test/resources/fixtures/data/scriptRevision/100.json +++ b/src/test/resources/fixtures/data/scriptRevision/100.json @@ -5,6 +5,8 @@ "id": "100", "name": "Hello, Script Revision", "sequenceNo": "22", + "commitMessage": "Initial checkin", + "author": "Jon Programmer", "createDate": "2023-02-18T00:47:51Z", "modifyDate": "2023-02-18T00:47:51Z" }, @@ -15,5 +17,20 @@ "sequenceNo": "22", "createDate": "2023-02-18T00:47:51Z", "modifyDate": "2023-02-18T00:47:51Z" + }, + "associatedRecords": { + "files": [ + { + "tableName": "scriptRevisionFile", + "values": { + "id": 101, + "fileName": "Script.js", + "contents": "var hello;", + "scriptRevisionId": 100, + "createDate": "2023-06-23T21:59:57Z", + "modifyDate": "2023-06-23T21:59:57Z" + } + } + ] } } From 0c76371d59f549b3de4af4bbe132c52f84e30f8f Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 6 Sep 2023 08:25:17 -0500 Subject: [PATCH 3/5] Add maven-jar-plugin to publish qfmd's test classes in a jar (e.g., for inclusion in applications for selenium testing); Updates in library classes to support alternative usages --- pom.xml | 14 ++++ .../lib/QBaseSeleniumTest.java | 24 ++++-- .../materialdashboard/lib/QSeleniumLib.java | 84 +++++++++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 83eb339..e3768cc 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,20 @@ true + + + + maven-jar-plugin + + + package + + test-jar + + + + + diff --git a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java index 8f3ece1..e88b1b1 100755 --- a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java +++ b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QBaseSeleniumTest.java @@ -18,7 +18,7 @@ import org.openqa.selenium.chrome.ChromeOptions; *******************************************************************************/ public class QBaseSeleniumTest { - private static ChromeOptions chromeOptions; + protected static ChromeOptions chromeOptions; protected WebDriver driver; protected QSeleniumJavalin qSeleniumJavalin; @@ -52,15 +52,29 @@ public class QBaseSeleniumTest ** *******************************************************************************/ @BeforeEach - void beforeEach() + public void beforeEach() { driver = new ChromeDriver(chromeOptions); driver.manage().window().setSize(new Dimension(1700, 1300)); qSeleniumLib = new QSeleniumLib(driver); - qSeleniumJavalin = new QSeleniumJavalin(); - addJavalinRoutes(qSeleniumJavalin); - qSeleniumJavalin.start(); + if(useInternalJavalin()) + { + qSeleniumJavalin = new QSeleniumJavalin(); + addJavalinRoutes(qSeleniumJavalin); + qSeleniumJavalin.start(); + } + } + + + + /******************************************************************************* + ** control if the test needs to start its own javalin server, or if we're running + ** in an environment where an external web server is being used. + *******************************************************************************/ + protected boolean useInternalJavalin() + { + return (true); } diff --git a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QSeleniumLib.java b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QSeleniumLib.java index 9bbc344..2b28423 100755 --- a/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QSeleniumLib.java +++ b/src/test/java/com/kingsrook/qqq/materialdashboard/lib/QSeleniumLib.java @@ -5,6 +5,7 @@ import java.io.File; import java.time.Duration; import java.util.List; import java.util.Objects; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -96,6 +97,17 @@ public class QSeleniumLib + /******************************************************************************* + ** Getter for BASE_URL + ** + *******************************************************************************/ + public String getBaseUrl() + { + return BASE_URL; + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -265,6 +277,31 @@ public class QSeleniumLib + /******************************************************************************* + ** + *******************************************************************************/ + public void waitForNumberOfWindowsToBe(int number) + { + LOG.debug("Waiting for number of windows (tabs) to be [" + number + "]"); + long start = System.currentTimeMillis(); + + do + { + if(driver.getWindowHandles().size() == number) + { + LOG.debug("Number of windows (tabs) is [" + number + "]"); + return; + } + + sleepABit(); + } + while(start + (1000 * WAIT_SECONDS) > System.currentTimeMillis()); + + fail("Failed waiting for number of windows (tabs) to be [" + number + "] after [" + WAIT_SECONDS + "] seconds."); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -293,6 +330,53 @@ public class QSeleniumLib + /******************************************************************************* + ** + *******************************************************************************/ + public void switchToSecondaryTab() + { + String originalWindow = driver.getWindowHandle(); + + waitForNumberOfWindowsToBe(2); + + Set windowHandles = driver.getWindowHandles(); + for(String windowHandle : windowHandles) + { + if(!windowHandle.equals(originalWindow)) + { + driver.switchTo().window(windowHandle); + return; + } + } + + fail("Failed to find a window handle not equal to the original window handle. Original=[" + originalWindow + "]. All=[" + windowHandles + "]"); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public void closeSecondaryTab() + { + String originalWindow = driver.getWindowHandle(); + driver.close(); + + Set windowHandles = driver.getWindowHandles(); + for(String windowHandle : windowHandles) + { + if(!windowHandle.equals(originalWindow)) + { + driver.switchTo().window(windowHandle); + return; + } + } + + fail("Failed to find a window handle not equal to the original window handle. Original=[" + originalWindow + "]. All=[" + windowHandles + "]"); + } + + + @FunctionalInterface public interface Code { From da0947b538e9e23bc6c5c8179a3498584c7345cb Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 6 Sep 2023 08:47:20 -0500 Subject: [PATCH 4/5] Trying to fix chrome/orb fun. See https://github.com/CircleCI-Public/browser-tools-orb/issues/75 --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7e913d2..1739217 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,6 +29,7 @@ commands: mvn_verify: steps: + - run: sudo apt-get update - browser-tools/install-chrome - browser-tools/install-chromedriver - run: From eeb1b37d1801acba6984a12ef9f89925ba72d0a8 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 6 Sep 2023 08:50:06 -0500 Subject: [PATCH 5/5] Trying to fix chrome/orb fun by updating orb version to latest --- .circleci/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1739217..c6bf029 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 orbs: node: circleci/node@5.1.0 - browser-tools: circleci/browser-tools@1.4.3 + browser-tools: circleci/browser-tools@1.4.5 executors: java17: @@ -29,7 +29,6 @@ commands: mvn_verify: steps: - - run: sudo apt-get update - browser-tools/install-chrome - browser-tools/install-chromedriver - run: