diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7e913d2..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:
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/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..649d82b 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);
}
@@ -75,6 +89,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/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
{
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/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 8de0400..955ab34 100644
--- a/src/test/resources/fixtures/data/scriptRevision/100.json
+++ b/src/test/resources/fixtures/data/scriptRevision/100.json
@@ -1,14 +1,22 @@
{
"tableName": "scriptRevision",
+ "recordLabel": "Hello, Script Revision",
"values": {
- "id": 100,
+ "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"
},
"displayValues": {
-
+ "id": "1",
+ "name": "Hello, Script Revision",
+ "scriptId": "1",
+ "sequenceNo": "22",
+ "createDate": "2023-02-18T00:47:51Z",
+ "modifyDate": "2023-02-18T00:47:51Z"
},
"associatedRecords": {
"files": [
@@ -25,4 +33,4 @@
}
]
}
-}
\ 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
+ }
+}