mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Merge remote-tracking branch 'origin/feature/deploy-test-jar'
This commit is contained in:
@ -2,7 +2,7 @@ version: 2.1
|
|||||||
|
|
||||||
orbs:
|
orbs:
|
||||||
node: circleci/node@5.1.0
|
node: circleci/node@5.1.0
|
||||||
browser-tools: circleci/browser-tools@1.4.3
|
browser-tools: circleci/browser-tools@1.4.5
|
||||||
|
|
||||||
executors:
|
executors:
|
||||||
java17:
|
java17:
|
||||||
|
14
pom.xml
14
pom.xml
@ -161,6 +161,20 @@
|
|||||||
<skipUpdateVersion>true</skipUpdateVersion>
|
<skipUpdateVersion>true</skipUpdateVersion>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Publish this project's test code as a jar -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
document.removeEventListener("keydown", down)
|
document.removeEventListener("keydown", down)
|
||||||
}
|
}
|
||||||
}, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData])
|
}, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData, location])
|
||||||
|
|
||||||
const gotoCreate = () =>
|
const gotoCreate = () =>
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ import org.openqa.selenium.chrome.ChromeOptions;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QBaseSeleniumTest
|
public class QBaseSeleniumTest
|
||||||
{
|
{
|
||||||
private static ChromeOptions chromeOptions;
|
protected static ChromeOptions chromeOptions;
|
||||||
|
|
||||||
protected WebDriver driver;
|
protected WebDriver driver;
|
||||||
protected QSeleniumJavalin qSeleniumJavalin;
|
protected QSeleniumJavalin qSeleniumJavalin;
|
||||||
@ -52,15 +52,29 @@ public class QBaseSeleniumTest
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach()
|
public void beforeEach()
|
||||||
{
|
{
|
||||||
driver = new ChromeDriver(chromeOptions);
|
driver = new ChromeDriver(chromeOptions);
|
||||||
driver.manage().window().setSize(new Dimension(1700, 1300));
|
driver.manage().window().setSize(new Dimension(1700, 1300));
|
||||||
qSeleniumLib = new QSeleniumLib(driver);
|
qSeleniumLib = new QSeleniumLib(driver);
|
||||||
|
|
||||||
qSeleniumJavalin = new QSeleniumJavalin();
|
if(useInternalJavalin())
|
||||||
addJavalinRoutes(qSeleniumJavalin);
|
{
|
||||||
qSeleniumJavalin.start();
|
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/authentication", "metaData/authentication.json")
|
||||||
.withRouteToFile("/metaData/table/person", "metaData/table/person.json")
|
.withRouteToFile("/metaData/table/person", "metaData/table/person.json")
|
||||||
.withRouteToFile("/metaData/table/city", "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");
|
.withRouteToFile("/processes/querySavedFilter/init", "processes/querySavedFilter/init.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import java.io.File;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
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<String> 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<String> 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
|
@FunctionalInterface
|
||||||
public interface Code<T>
|
public interface Code<T>
|
||||||
{
|
{
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -64,8 +64,6 @@ public class ScriptTableTest extends QBaseSeleniumTest
|
|||||||
qSeleniumLib.waitForSelectorContaining("DIV.ace_line", "var hello;");
|
qSeleniumLib.waitForSelectorContaining("DIV.ace_line", "var hello;");
|
||||||
qSeleniumLib.waitForSelectorContaining("DIV", "2nd commit");
|
qSeleniumLib.waitForSelectorContaining("DIV", "2nd commit");
|
||||||
qSeleniumLib.waitForSelectorContaining("DIV", "Initial checkin");
|
qSeleniumLib.waitForSelectorContaining("DIV", "Initial checkin");
|
||||||
|
|
||||||
qSeleniumLib.waitForever();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
{
|
{
|
||||||
"tableName": "scriptRevision",
|
"tableName": "scriptRevision",
|
||||||
|
"recordLabel": "Hello, Script Revision",
|
||||||
"values": {
|
"values": {
|
||||||
"id": 100,
|
"id": "100",
|
||||||
|
"name": "Hello, Script Revision",
|
||||||
|
"sequenceNo": "22",
|
||||||
"commitMessage": "Initial checkin",
|
"commitMessage": "Initial checkin",
|
||||||
"author": "Jon Programmer",
|
"author": "Jon Programmer",
|
||||||
"createDate": "2023-02-18T00:47:51Z",
|
"createDate": "2023-02-18T00:47:51Z",
|
||||||
"modifyDate": "2023-02-18T00:47:51Z"
|
"modifyDate": "2023-02-18T00:47:51Z"
|
||||||
},
|
},
|
||||||
"displayValues": {
|
"displayValues": {
|
||||||
|
"id": "1",
|
||||||
|
"name": "Hello, Script Revision",
|
||||||
|
"scriptId": "1",
|
||||||
|
"sequenceNo": "22",
|
||||||
|
"createDate": "2023-02-18T00:47:51Z",
|
||||||
|
"modifyDate": "2023-02-18T00:47:51Z"
|
||||||
},
|
},
|
||||||
"associatedRecords": {
|
"associatedRecords": {
|
||||||
"files": [
|
"files": [
|
||||||
@ -25,4 +33,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,8 @@
|
|||||||
"capabilities": [
|
"capabilities": [
|
||||||
"TABLE_COUNT",
|
"TABLE_COUNT",
|
||||||
"TABLE_GET",
|
"TABLE_GET",
|
||||||
"TABLE_QUERY"
|
"TABLE_QUERY",
|
||||||
|
"TABLE_UPDATE"
|
||||||
],
|
],
|
||||||
"readPermission": true,
|
"readPermission": true,
|
||||||
"insertPermission": true,
|
"insertPermission": true,
|
||||||
|
152
src/test/resources/fixtures/metaData/table/scriptRevision.json
Normal file
152
src/test/resources/fixtures/metaData/table/scriptRevision.json
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user