mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Script Tests and further enhancements
This commit is contained in:
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.backend.core.actions.scripts;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.BuildScriptLogAndScriptLogLineExecutionLogger;
|
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Class for running a test of a script - e.g., maybe before it is saved.
|
|
||||||
*******************************************************************************/
|
|
||||||
public class TestScriptAction
|
|
||||||
{
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public void run(TestScriptInput input, TestScriptOutput output) throws QException
|
|
||||||
{
|
|
||||||
QTableMetaData table = input.getTable();
|
|
||||||
|
|
||||||
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(input.getInstance());
|
|
||||||
executeCodeInput.setSession(input.getSession());
|
|
||||||
executeCodeInput.setInput(new HashMap<>(input.getInputValues()));
|
|
||||||
executeCodeInput.setContext(new HashMap<>());
|
|
||||||
// todo! if(input.getOutputObject() != null)
|
|
||||||
// todo! {
|
|
||||||
// todo! executeCodeInput.getContext().put("output", input.getOutputObject());
|
|
||||||
// todo! }
|
|
||||||
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(input.getCode()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
|
||||||
executeCodeInput.setExecutionLogger(new BuildScriptLogAndScriptLogLineExecutionLogger());
|
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
|
||||||
|
|
||||||
// todo! output.setOutput(executeCodeOutput.getOutput());
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.core.actions.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.BuildScriptLogAndScriptLogLineExecutionLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Interface to be implemented by script-running actions, if they want to allow
|
||||||
|
** themselves to be used for user-testing of their script.
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface TestScriptActionInterface
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
** Called to adapt or translate data from the TestScriptInput (which would just
|
||||||
|
** have a map of name-value pairs) to the actual input object(s) used by the script.
|
||||||
|
**
|
||||||
|
** Note - such a method may want or need to put an "output" object into the
|
||||||
|
** executeCodeInput's context map.
|
||||||
|
*******************************************************************************/
|
||||||
|
void setupTestScriptInput(TestScriptInput testScriptInput, ExecuteCodeInput executeCodeInput);
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Called to adapt or translate the output object of the script execution to
|
||||||
|
** something suitable for returning to the caller.
|
||||||
|
**
|
||||||
|
** Default implementation may always be suitable?
|
||||||
|
*******************************************************************************/
|
||||||
|
default Serializable processTestScriptOutput(ExecuteCodeOutput executeCodeOutput)
|
||||||
|
{
|
||||||
|
return (executeCodeOutput.getOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Define the list of input fields for testing the script. The names of these
|
||||||
|
** fields will end up as keys in the setupTestScriptInput method's testScriptInput object.
|
||||||
|
*******************************************************************************/
|
||||||
|
List<QFieldMetaData> getTestInputFields();
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Define the list of output fields when testing the script. The output object
|
||||||
|
** returned from processTestScriptOutput should have keys that match these field names.
|
||||||
|
*******************************************************************************/
|
||||||
|
List<QFieldMetaData> getTestOutputFields();
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Execute a test script.
|
||||||
|
*******************************************************************************/
|
||||||
|
default void execute(TestScriptInput input, TestScriptOutput output) throws QException
|
||||||
|
{
|
||||||
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(input.getInstance());
|
||||||
|
executeCodeInput.setSession(input.getSession());
|
||||||
|
executeCodeInput.setContext(new HashMap<>());
|
||||||
|
|
||||||
|
executeCodeInput.setCodeReference(input.getCodeReference());
|
||||||
|
BuildScriptLogAndScriptLogLineExecutionLogger executionLogger = new BuildScriptLogAndScriptLogLineExecutionLogger(null, null);
|
||||||
|
executeCodeInput.setExecutionLogger(executionLogger);
|
||||||
|
|
||||||
|
setupTestScriptInput(input, executeCodeInput);
|
||||||
|
|
||||||
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
output.setOutputObject(processTestScriptOutput(executeCodeOutput));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
output.setException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.setScriptLog(executionLogger.getScriptLog());
|
||||||
|
output.setScriptLogLines(executionLogger.getScriptLogLines());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -230,7 +230,7 @@ public class QInstanceEnricher
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void enrichField(QFieldMetaData field)
|
public void enrichField(QFieldMetaData field)
|
||||||
{
|
{
|
||||||
if(!StringUtils.hasContent(field.getLabel()))
|
if(!StringUtils.hasContent(field.getLabel()))
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -33,10 +34,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class TestScriptInput extends AbstractTableActionInput
|
public class TestScriptInput extends AbstractTableActionInput
|
||||||
{
|
{
|
||||||
private Serializable recordPrimaryKey;
|
private Map<String, Serializable> inputValues;
|
||||||
private String code;
|
private QCodeReference codeReference;
|
||||||
private Serializable scriptTypeId;
|
|
||||||
private Map<String, String> inputValues;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -50,45 +49,11 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for recordPrimaryKey
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public Serializable getRecordPrimaryKey()
|
|
||||||
{
|
|
||||||
return recordPrimaryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Setter for recordPrimaryKey
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public void setRecordPrimaryKey(Serializable recordPrimaryKey)
|
|
||||||
{
|
|
||||||
this.recordPrimaryKey = recordPrimaryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Fluent setter for recordPrimaryKey
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public TestScriptInput withRecordPrimaryKey(Serializable recordPrimaryKey)
|
|
||||||
{
|
|
||||||
this.recordPrimaryKey = recordPrimaryKey;
|
|
||||||
return (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for inputValues
|
** Getter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Map<String, String> getInputValues()
|
public Map<String, Serializable> getInputValues()
|
||||||
{
|
{
|
||||||
return inputValues;
|
return inputValues;
|
||||||
}
|
}
|
||||||
@ -99,7 +64,7 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
** Setter for inputValues
|
** Setter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setInputValues(Map<String, String> inputValues)
|
public void setInputValues(Map<String, Serializable> inputValues)
|
||||||
{
|
{
|
||||||
this.inputValues = inputValues;
|
this.inputValues = inputValues;
|
||||||
}
|
}
|
||||||
@ -110,7 +75,7 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
** Fluent setter for inputValues
|
** Fluent setter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public TestScriptInput withInputValues(Map<String, String> inputValues)
|
public TestScriptInput withInputValues(Map<String, Serializable> inputValues)
|
||||||
{
|
{
|
||||||
this.inputValues = inputValues;
|
this.inputValues = inputValues;
|
||||||
return (this);
|
return (this);
|
||||||
@ -119,68 +84,34 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for code
|
** Getter for codeReference
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public String getCode()
|
public QCodeReference getCodeReference()
|
||||||
{
|
{
|
||||||
return code;
|
return codeReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for code
|
** Setter for codeReference
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setCode(String code)
|
public void setCodeReference(QCodeReference codeReference)
|
||||||
{
|
{
|
||||||
this.code = code;
|
this.codeReference = codeReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Fluent setter for code
|
** Fluent setter for codeReference
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public TestScriptInput withCode(String code)
|
public TestScriptInput withCodeReference(QCodeReference codeReference)
|
||||||
{
|
{
|
||||||
this.code = code;
|
this.codeReference = codeReference;
|
||||||
return (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for scriptTypeId
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public Serializable getScriptTypeId()
|
|
||||||
{
|
|
||||||
return scriptTypeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Setter for scriptTypeId
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public void setScriptTypeId(Serializable scriptTypeId)
|
|
||||||
{
|
|
||||||
this.scriptTypeId = scriptTypeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Fluent setter for scriptTypeId
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public TestScriptInput withScriptTypeId(Serializable scriptTypeId)
|
|
||||||
{
|
|
||||||
this.scriptTypeId = scriptTypeId;
|
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,10 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.actions.scripts;
|
package com.kingsrook.qqq.backend.core.model.actions.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -30,4 +33,103 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class TestScriptOutput extends AbstractActionOutput
|
public class TestScriptOutput extends AbstractActionOutput
|
||||||
{
|
{
|
||||||
|
private Serializable outputObject;
|
||||||
|
private Exception exception;
|
||||||
|
private QRecord scriptLog;
|
||||||
|
private List<QRecord> scriptLogLines;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Serializable getOutputObject()
|
||||||
|
{
|
||||||
|
return outputObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setOutputObject(Serializable outputObject)
|
||||||
|
{
|
||||||
|
this.outputObject = outputObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public TestScriptOutput withOutputObject(Serializable outputObject)
|
||||||
|
{
|
||||||
|
this.outputObject = outputObject;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setException(Exception exception)
|
||||||
|
{
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Exception getException()
|
||||||
|
{
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setScriptLog(QRecord scriptLog)
|
||||||
|
{
|
||||||
|
this.scriptLog = scriptLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QRecord getScriptLog()
|
||||||
|
{
|
||||||
|
return scriptLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setScriptLogLines(List<QRecord> scriptLogLines)
|
||||||
|
{
|
||||||
|
this.scriptLogLines = scriptLogLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QRecord> getScriptLogLines()
|
||||||
|
{
|
||||||
|
return scriptLogLines;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,6 @@ public enum QCodeUsage
|
|||||||
CUSTOMIZER, // a function to customize part of a QQQ table's behavior
|
CUSTOMIZER, // a function to customize part of a QQQ table's behavior
|
||||||
POSSIBLE_VALUE_PROVIDER, // code that drives a custom possibleValueSource
|
POSSIBLE_VALUE_PROVIDER, // code that drives a custom possibleValueSource
|
||||||
RECORD_AUTOMATION_HANDLER, // code that executes record automations
|
RECORD_AUTOMATION_HANDLER, // code that executes record automations
|
||||||
REPORT_STATIC_DATA_SUPPLIER // code that supplies static data to a report
|
REPORT_STATIC_DATA_SUPPLIER, // code that supplies static data to a report
|
||||||
|
SCRIPT_TESTER // class that is used to test scripts.
|
||||||
}
|
}
|
||||||
|
@ -98,4 +98,20 @@ public enum AdornmentType
|
|||||||
String XLARGE = "xlarge";
|
String XLARGE = "xlarge";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface CodeEditorValues
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static Pair<String, Serializable> languageMode(String languageMode)
|
||||||
|
{
|
||||||
|
return (new Pair<>("languageMode", languageMode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -30,8 +31,9 @@ import java.io.Serializable;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class AssociatedScript implements Serializable
|
public class AssociatedScript implements Serializable
|
||||||
{
|
{
|
||||||
private String fieldName;
|
private String fieldName;
|
||||||
private Serializable scriptTypeId;
|
private Serializable scriptTypeId;
|
||||||
|
private QCodeReference scriptTester;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -101,4 +103,38 @@ public class AssociatedScript implements Serializable
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for scriptTester
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QCodeReference getScriptTester()
|
||||||
|
{
|
||||||
|
return scriptTester;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for scriptTester
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setScriptTester(QCodeReference scriptTester)
|
||||||
|
{
|
||||||
|
this.scriptTester = scriptTester;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for scriptTester
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public AssociatedScript withScriptTester(QCodeReference scriptTester)
|
||||||
|
{
|
||||||
|
this.scriptTester = scriptTester;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,13 @@ public class Script extends QRecordEntity
|
|||||||
{
|
{
|
||||||
public static final String TABLE_NAME = "script";
|
public static final String TABLE_NAME = "script";
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant createDate;
|
private Instant createDate;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
|
@ -35,13 +35,13 @@ public class ScriptLog extends QRecordEntity
|
|||||||
{
|
{
|
||||||
public static final String TABLE_NAME = "scriptLog";
|
public static final String TABLE_NAME = "scriptLog";
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant createDate;
|
private Instant createDate;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField(possibleValueSourceName = "script")
|
@QField(possibleValueSourceName = "script")
|
||||||
|
@ -34,13 +34,13 @@ public class ScriptLogLine extends QRecordEntity
|
|||||||
{
|
{
|
||||||
public static final String TABLE_NAME = "scriptLogLine";
|
public static final String TABLE_NAME = "scriptLogLine";
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant createDate;
|
private Instant createDate;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField(possibleValueSourceName = "scriptLog")
|
@QField(possibleValueSourceName = "scriptLog")
|
||||||
|
@ -36,13 +36,13 @@ public class ScriptRevision extends QRecordEntity
|
|||||||
{
|
{
|
||||||
public static final String TABLE_NAME = "scriptRevision";
|
public static final String TABLE_NAME = "scriptRevision";
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant createDate;
|
private Instant createDate;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField(possibleValueSourceName = "script")
|
@QField(possibleValueSourceName = "script")
|
||||||
|
@ -34,13 +34,13 @@ public class ScriptType extends QRecordEntity
|
|||||||
{
|
{
|
||||||
public static final String TABLE_NAME = "scriptType";
|
public static final String TABLE_NAME = "scriptType";
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant createDate;
|
private Instant createDate;
|
||||||
|
|
||||||
@QField()
|
@QField(isEditable = false)
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
|
@ -163,7 +163,8 @@ public class ScriptsMetaDataProvider
|
|||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name")))
|
||||||
.withSection(new QFieldSection("details", new QIcon().withName("dataset"), Tier.T2, List.of("helpText", "sampleCode")))
|
.withSection(new QFieldSection("details", new QIcon().withName("dataset"), Tier.T2, List.of("helpText", "sampleCode")))
|
||||||
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
||||||
tableMetaData.getField("sampleCode").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR));
|
tableMetaData.getField("sampleCode").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR).withValue(AdornmentType.CodeEditorValues.languageMode("javascript")));
|
||||||
|
tableMetaData.getField("helpText").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR).withValue(AdornmentType.CodeEditorValues.languageMode("text")));
|
||||||
return (tableMetaData);
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class BasicETLExtractFunction implements BackendStep
|
|||||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
{
|
{
|
||||||
String tableName = runBackendStepInput.getValueString(BasicETLProcess.FIELD_SOURCE_TABLE);
|
String tableName = runBackendStepInput.getValueString(BasicETLProcess.FIELD_SOURCE_TABLE);
|
||||||
LOG.info("Start query on table: " + tableName);
|
LOG.debug("Start query on table: " + tableName);
|
||||||
|
|
||||||
QueryInput queryInput = new QueryInput(runBackendStepInput.getInstance());
|
QueryInput queryInput = new QueryInput(runBackendStepInput.getInstance());
|
||||||
queryInput.setSession(runBackendStepInput.getSession());
|
queryInput.setSession(runBackendStepInput.getSession());
|
||||||
@ -70,7 +70,7 @@ public class BasicETLExtractFunction implements BackendStep
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// if the caller gave us a record pipe, pass it to the query action //
|
// if the caller gave us a record pipe, pass it to the query action //
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
if (recordPipe != null)
|
if(recordPipe != null)
|
||||||
{
|
{
|
||||||
queryInput.setRecordPipe(recordPipe);
|
queryInput.setRecordPipe(recordPipe);
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ public class BasicETLExtractFunction implements BackendStep
|
|||||||
QueryAction queryAction = new QueryAction();
|
QueryAction queryAction = new QueryAction();
|
||||||
QueryOutput queryOutput = queryAction.execute(queryInput);
|
QueryOutput queryOutput = queryAction.execute(queryInput);
|
||||||
|
|
||||||
if (recordPipe == null)
|
if(recordPipe == null)
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// only return the records (and log about them) if there's no record pipe //
|
// only return the records (and log about them) if there's no record pipe //
|
||||||
|
@ -60,13 +60,14 @@ public class BasicETLLoadFunction implements BackendStep
|
|||||||
// exit early with no-op if no records made it here //
|
// exit early with no-op if no records made it here //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
List<QRecord> inputRecords = runBackendStepInput.getRecords();
|
List<QRecord> inputRecords = runBackendStepInput.getRecords();
|
||||||
LOG.info("Received [" + inputRecords.size() + "] records to load");
|
|
||||||
if(CollectionUtils.nullSafeIsEmpty(inputRecords))
|
if(CollectionUtils.nullSafeIsEmpty(inputRecords))
|
||||||
{
|
{
|
||||||
runBackendStepOutput.addValue(BasicETLProcess.FIELD_RECORD_COUNT, 0);
|
runBackendStepOutput.addValue(BasicETLProcess.FIELD_RECORD_COUNT, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG.info("Received [" + inputRecords.size() + "] records to load");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
// put the destination table name in all records being inserted //
|
// put the destination table name in all records being inserted //
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
@ -59,21 +59,21 @@ public class BasicETLTransformFunction implements BackendStep
|
|||||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
{
|
{
|
||||||
String tableName = runBackendStepInput.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE);
|
String tableName = runBackendStepInput.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE);
|
||||||
LOG.info("Start transform for destination table: " + tableName);
|
LOG.debug("Start transform for destination table: " + tableName);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// exit early with no-op if no records made it here, or if we don't have a mapping to use //
|
// exit early with no-op if no records made it here, or if we don't have a mapping to use //
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if(CollectionUtils.nullSafeIsEmpty(runBackendStepInput.getRecords()))
|
if(CollectionUtils.nullSafeIsEmpty(runBackendStepInput.getRecords()))
|
||||||
{
|
{
|
||||||
LOG.info("Exiting early with no-op for empty input record list.");
|
LOG.debug("Exiting early with no-op for empty input record list.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String mappingJSON = runBackendStepInput.getValueString(BasicETLProcess.FIELD_MAPPING_JSON);
|
String mappingJSON = runBackendStepInput.getValueString(BasicETLProcess.FIELD_MAPPING_JSON);
|
||||||
if(!StringUtils.hasContent(mappingJSON))
|
if(!StringUtils.hasContent(mappingJSON))
|
||||||
{
|
{
|
||||||
LOG.info("Exiting early with no-op for empty mappingJSON.");
|
LOG.debug("Exiting early with no-op for empty mappingJSON.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.core.actions.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for TestScriptActionInterface
|
||||||
|
*******************************************************************************/
|
||||||
|
class TestScriptActionInterfaceTest
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void test() throws QException
|
||||||
|
{
|
||||||
|
QInstance qInstance = TestUtils.defineInstance();
|
||||||
|
|
||||||
|
TestScriptInput testScriptInput = new TestScriptInput(qInstance);
|
||||||
|
testScriptInput.setSession(new QSession());
|
||||||
|
testScriptInput.setInputValues(Map.of("name", "Darin", "age", 42));
|
||||||
|
testScriptInput.setCodeReference(new QCodeReference(SampleScript.class, QCodeUsage.CUSTOMIZER));
|
||||||
|
TestScriptOutput testScriptOutput = new TestScriptOutput();
|
||||||
|
new SampleTestAction().execute(testScriptInput, testScriptOutput);
|
||||||
|
|
||||||
|
assertNull(testScriptOutput.getException());
|
||||||
|
assertTrue(testScriptOutput.getOutputObject() instanceof SampleTestOutput);
|
||||||
|
SampleTestOutput sampleTestOutput = (SampleTestOutput) testScriptOutput.getOutputObject();
|
||||||
|
assertEquals("Darin is 42 years old!", sampleTestOutput.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleScript implements Function<Map<String, Object>, Serializable>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Serializable apply(Map<String, Object> context)
|
||||||
|
{
|
||||||
|
SampleTestInput input = (SampleTestInput) context.get("input");
|
||||||
|
SampleTestOutput output = (SampleTestOutput) context.get("output");
|
||||||
|
output.setMessage(input.getName() + " is " + input.getAge() + " years old!");
|
||||||
|
return (output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleTestAction implements TestScriptActionInterface
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void setupTestScriptInput(TestScriptInput testScriptInput, ExecuteCodeInput executeCodeInput)
|
||||||
|
{
|
||||||
|
SampleTestInput sampleTestInput = new SampleTestInput();
|
||||||
|
sampleTestInput.setName(ValueUtils.getValueAsString(testScriptInput.getInputValues().get("name")));
|
||||||
|
sampleTestInput.setAge(ValueUtils.getValueAsInteger(testScriptInput.getInputValues().get("age")));
|
||||||
|
executeCodeInput.setInput(Map.of("input", sampleTestInput));
|
||||||
|
|
||||||
|
executeCodeInput.getContext().put("output", new SampleTestOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QFieldMetaData> getTestInputFields()
|
||||||
|
{
|
||||||
|
return List.of(
|
||||||
|
new QFieldMetaData("name", QFieldType.STRING),
|
||||||
|
new QFieldMetaData("age", QFieldType.INTEGER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QFieldMetaData> getTestOutputFields()
|
||||||
|
{
|
||||||
|
return List.of(new QFieldMetaData("message", QFieldType.STRING));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleTestInput implements Serializable
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for age
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer getAge()
|
||||||
|
{
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for age
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAge(Integer age)
|
||||||
|
{
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleTestOutput implements Serializable
|
||||||
|
{
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for message
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for message
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setMessage(String message)
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.backend.core.actions.scripts;
|
|
||||||
|
|
||||||
|
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Unit test for TestScriptAction
|
|
||||||
*******************************************************************************/
|
|
||||||
class TestScriptActionTest
|
|
||||||
{
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
@Disabled("Not yet done.")
|
|
||||||
void test() throws QException
|
|
||||||
{
|
|
||||||
QInstance instance = TestUtils.defineInstance();
|
|
||||||
TestScriptInput input = new TestScriptInput(instance);
|
|
||||||
TestScriptOutput output = new TestScriptOutput();
|
|
||||||
new TestScriptAction().run(input, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -57,7 +57,7 @@ public class BasicETLCleanupSourceFilesStep implements BackendStep
|
|||||||
public static final String FIELD_MOVE_OR_DELETE = "moveOrDelete";
|
public static final String FIELD_MOVE_OR_DELETE = "moveOrDelete";
|
||||||
public static final String FIELD_DESTINATION_FOR_MOVES = "destinationForMoves";
|
public static final String FIELD_DESTINATION_FOR_MOVES = "destinationForMoves";
|
||||||
|
|
||||||
public static final String VALUE_MOVE = "move";
|
public static final String VALUE_MOVE = "move";
|
||||||
public static final String VALUE_DELETE = "delete";
|
public static final String VALUE_DELETE = "delete";
|
||||||
public static final String STEP_NAME = "cleanupSourceFiles";
|
public static final String STEP_NAME = "cleanupSourceFiles";
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ public class BasicETLCleanupSourceFilesStep implements BackendStep
|
|||||||
String sourceFilePaths = runBackendStepInput.getValueString(BasicETLCollectSourceFileNamesStep.FIELD_SOURCE_FILE_PATHS);
|
String sourceFilePaths = runBackendStepInput.getValueString(BasicETLCollectSourceFileNamesStep.FIELD_SOURCE_FILE_PATHS);
|
||||||
if(!StringUtils.hasContent(sourceFilePaths))
|
if(!StringUtils.hasContent(sourceFilePaths))
|
||||||
{
|
{
|
||||||
LOG.info("No source file paths were specified in field [" + BasicETLCollectSourceFileNamesStep.FIELD_SOURCE_FILE_PATHS + "]");
|
LOG.debug("No source file paths were specified in field [" + BasicETLCollectSourceFileNamesStep.FIELD_SOURCE_FILE_PATHS + "]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,12 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.kingsrook.qqq</groupId>
|
||||||
|
<artifactId>qqq-language-support-javascript</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 3rd party deps specifically for this module -->
|
<!-- 3rd party deps specifically for this module -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -42,8 +42,6 @@ import com.kingsrook.qqq.backend.core.actions.metadata.MetaDataAction;
|
|||||||
import com.kingsrook.qqq.backend.core.actions.metadata.ProcessMetaDataAction;
|
import com.kingsrook.qqq.backend.core.actions.metadata.ProcessMetaDataAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.metadata.TableMetaDataAction;
|
import com.kingsrook.qqq.backend.core.actions.metadata.TableMetaDataAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.reporting.ExportAction;
|
import com.kingsrook.qqq.backend.core.actions.reporting.ExportAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.StoreAssociatedScriptAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
@ -68,10 +66,6 @@ import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||||
@ -80,9 +74,6 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||||
@ -95,13 +86,11 @@ import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.AssociatedScript;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
import com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule;
|
import com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule;
|
||||||
import com.kingsrook.qqq.backend.core.modules.authentication.QAuthenticationModuleDispatcher;
|
import com.kingsrook.qqq.backend.core.modules.authentication.QAuthenticationModuleDispatcher;
|
||||||
import com.kingsrook.qqq.backend.core.modules.authentication.QAuthenticationModuleInterface;
|
import com.kingsrook.qqq.backend.core.modules.authentication.QAuthenticationModuleInterface;
|
||||||
import com.kingsrook.qqq.backend.core.processes.utils.GeneralProcessUtils;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
|
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
@ -109,7 +98,6 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
import io.javalin.Javalin;
|
import io.javalin.Javalin;
|
||||||
import io.javalin.apibuilder.EndpointGroup;
|
import io.javalin.apibuilder.EndpointGroup;
|
||||||
import io.javalin.http.ContentType;
|
|
||||||
import io.javalin.http.Context;
|
import io.javalin.http.Context;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -308,10 +296,7 @@ public class QJavalinImplementation
|
|||||||
put("", QJavalinImplementation::dataUpdate); // todo - want different semantics??
|
put("", QJavalinImplementation::dataUpdate); // todo - want different semantics??
|
||||||
delete("", QJavalinImplementation::dataDelete);
|
delete("", QJavalinImplementation::dataDelete);
|
||||||
|
|
||||||
get("/developer", QJavalinImplementation::getRecordDeveloperMode);
|
QJavalinScriptsHandler.defineRecordRoutes();
|
||||||
post("/developer/associatedScript/{fieldName}", QJavalinImplementation::storeRecordAssociatedScript);
|
|
||||||
get("/developer/associatedScript/{fieldName}/{scriptRevisionId}/logs", QJavalinImplementation::getAssociatedScriptLogs);
|
|
||||||
post("/developer/associatedScript/{fieldName}/test", QJavalinImplementation::testAssociatedScript);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -986,213 +971,6 @@ public class QJavalinImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private static void getRecordDeveloperMode(Context context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String tableName = context.pathParam("table");
|
|
||||||
QTableMetaData table = qInstance.getTable(tableName);
|
|
||||||
String primaryKey = context.pathParam("primaryKey");
|
|
||||||
GetInput getInput = new GetInput(qInstance);
|
|
||||||
|
|
||||||
setupSession(context, getInput);
|
|
||||||
getInput.setTableName(tableName);
|
|
||||||
getInput.setShouldGenerateDisplayValues(true);
|
|
||||||
getInput.setShouldTranslatePossibleValues(true);
|
|
||||||
|
|
||||||
// todo - validate that the primary key is of the proper type (e.g,. not a string for an id field)
|
|
||||||
// and throw a 400-series error (tell the user bad-request), rather than, we're doing a 500 (server error)
|
|
||||||
|
|
||||||
getInput.setPrimaryKey(primaryKey);
|
|
||||||
|
|
||||||
GetAction getAction = new GetAction();
|
|
||||||
GetOutput getOutput = getAction.execute(getInput);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// throw a not found error if the record isn't found //
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
QRecord record = getOutput.getRecord();
|
|
||||||
if(record == null)
|
|
||||||
{
|
|
||||||
throw (new QNotFoundException("Could not find " + table.getLabel() + " with "
|
|
||||||
+ table.getFields().get(table.getPrimaryKeyField()).getLabel() + " of " + primaryKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Serializable> rs = new HashMap<>();
|
|
||||||
rs.put("record", record);
|
|
||||||
|
|
||||||
ArrayList<HashMap<String, Serializable>> associatedScripts = new ArrayList<>();
|
|
||||||
rs.put("associatedScripts", associatedScripts);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// process each associated script type for the table //
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
for(AssociatedScript associatedScript : CollectionUtils.nonNullList(table.getAssociatedScripts()))
|
|
||||||
{
|
|
||||||
HashMap<String, Serializable> thisScriptData = new HashMap<>();
|
|
||||||
associatedScripts.add(thisScriptData);
|
|
||||||
thisScriptData.put("associatedScript", associatedScript);
|
|
||||||
|
|
||||||
String fieldName = associatedScript.getFieldName();
|
|
||||||
Serializable scriptId = record.getValue(fieldName);
|
|
||||||
if(scriptId != null)
|
|
||||||
{
|
|
||||||
GetInput getScriptInput = new GetInput(qInstance);
|
|
||||||
setupSession(context, getScriptInput);
|
|
||||||
getScriptInput.setTableName("script");
|
|
||||||
getScriptInput.setPrimaryKey(scriptId);
|
|
||||||
GetOutput getScriptOutput = new GetAction().execute(getScriptInput);
|
|
||||||
if(getScriptOutput.getRecord() != null)
|
|
||||||
{
|
|
||||||
thisScriptData.put("script", getScriptOutput.getRecord());
|
|
||||||
|
|
||||||
QueryInput queryInput = new QueryInput(qInstance);
|
|
||||||
setupSession(context, queryInput);
|
|
||||||
queryInput.setTableName("scriptRevision");
|
|
||||||
queryInput.setFilter(new QQueryFilter()
|
|
||||||
.withCriteria(new QFilterCriteria("scriptId", QCriteriaOperator.EQUALS, List.of(getScriptOutput.getRecord().getValue("id"))))
|
|
||||||
.withOrderBy(new QFilterOrderBy("id", false))
|
|
||||||
);
|
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
|
||||||
thisScriptData.put("scriptRevisions", new ArrayList<>(queryOutput.getRecords()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.result(JsonUtils.toJson(rs));
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
handleException(context, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
public static void getAssociatedScriptLogs(Context context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String scriptRevisionId = context.pathParam("scriptRevisionId");
|
|
||||||
|
|
||||||
QueryInput queryInput = new QueryInput(qInstance);
|
|
||||||
setupSession(context, queryInput);
|
|
||||||
queryInput.setTableName("scriptLog");
|
|
||||||
queryInput.setFilter(new QQueryFilter()
|
|
||||||
.withCriteria(new QFilterCriteria("scriptRevisionId", QCriteriaOperator.EQUALS, List.of(scriptRevisionId)))
|
|
||||||
.withOrderBy(new QFilterOrderBy("id", false))
|
|
||||||
);
|
|
||||||
queryInput.setLimit(100);
|
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
|
||||||
|
|
||||||
if(CollectionUtils.nullSafeHasContents(queryOutput.getRecords()))
|
|
||||||
{
|
|
||||||
GeneralProcessUtils.addForeignRecordsListToRecordList(queryInput, queryOutput.getRecords(), "id", "scriptLogLine", "scriptLogId");
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Serializable> rs = new HashMap<>();
|
|
||||||
rs.put("scriptLogRecords", new ArrayList<>(queryOutput.getRecords()));
|
|
||||||
|
|
||||||
context.result(JsonUtils.toJson(rs));
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
handleException(context, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private static void storeRecordAssociatedScript(Context context)
|
|
||||||
{
|
|
||||||
context.contentType(ContentType.APPLICATION_JSON);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StoreAssociatedScriptInput input = new StoreAssociatedScriptInput(qInstance);
|
|
||||||
setupSession(context, input);
|
|
||||||
input.setCode(context.formParam("contents"));
|
|
||||||
input.setCommitMessage(context.formParam("commitMessage"));
|
|
||||||
input.setFieldName(context.pathParam("fieldName"));
|
|
||||||
input.setTableName(context.pathParam("table"));
|
|
||||||
input.setRecordPrimaryKey(context.pathParam("primaryKey"));
|
|
||||||
|
|
||||||
StoreAssociatedScriptOutput output = new StoreAssociatedScriptOutput();
|
|
||||||
|
|
||||||
StoreAssociatedScriptAction storeAssociatedScriptAction = new StoreAssociatedScriptAction();
|
|
||||||
storeAssociatedScriptAction.run(input, output);
|
|
||||||
|
|
||||||
context.result(JsonUtils.toJson(output));
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
handleException(context, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private static void testAssociatedScript(Context context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
TestScriptInput input = new TestScriptInput(qInstance);
|
|
||||||
setupSession(context, input);
|
|
||||||
input.setTableName(context.pathParam("table"));
|
|
||||||
input.setRecordPrimaryKey(context.pathParam("primaryKey"));
|
|
||||||
// context.pathParam("fieldName");
|
|
||||||
Map<String, String> inputValues = new HashMap<>();
|
|
||||||
input.setInputValues(inputValues);
|
|
||||||
|
|
||||||
for(Map.Entry<String, List<String>> entry : context.formParamMap().entrySet())
|
|
||||||
{
|
|
||||||
String key = entry.getKey();
|
|
||||||
String value = entry.getValue().get(0);
|
|
||||||
|
|
||||||
if(key.equals("code"))
|
|
||||||
{
|
|
||||||
input.setCode(value);
|
|
||||||
}
|
|
||||||
else if(key.equals("scriptTypeId"))
|
|
||||||
{
|
|
||||||
input.setScriptTypeId(ValueUtils.getValueAsInteger(value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inputValues.put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TestScriptOutput output = new TestScriptOutput();
|
|
||||||
|
|
||||||
new TestScriptAction().run(input, output);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// todo - output to frontend - then add assertions in test. //
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
context.result(JsonUtils.toJson("OK"));
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
handleException(context, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -174,10 +174,10 @@ public class QJavalinProcessHandler
|
|||||||
return (new RunProcessAction().execute(runProcessInput));
|
return (new RunProcessAction().execute(runProcessInput));
|
||||||
});
|
});
|
||||||
|
|
||||||
LOG.info("Process result error? " + runProcessOutput.getException());
|
LOG.debug("Process result error? " + runProcessOutput.getException());
|
||||||
for(QFieldMetaData outputField : QJavalinImplementation.qInstance.getProcess(runProcessInput.getProcessName()).getOutputFields())
|
for(QFieldMetaData outputField : QJavalinImplementation.qInstance.getProcess(runProcessInput.getProcessName()).getOutputFields())
|
||||||
{
|
{
|
||||||
LOG.info("Process result output value: " + outputField.getName() + ": " + runProcessOutput.getValues().get(outputField.getName()));
|
LOG.debug("Process result output value: " + outputField.getName() + ": " + runProcessOutput.getValues().get(outputField.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeRunProcessResultForCaller(resultForCaller, runProcessOutput);
|
serializeRunProcessResultForCaller(resultForCaller, runProcessOutput);
|
||||||
|
@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.javalin;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.StoreAssociatedScriptAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptActionInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
|
import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.AssociatedScript;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.scripts.ScriptType;
|
||||||
|
import com.kingsrook.qqq.backend.core.processes.utils.GeneralProcessUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
|
import io.javalin.http.ContentType;
|
||||||
|
import io.javalin.http.Context;
|
||||||
|
import static io.javalin.apibuilder.ApiBuilder.get;
|
||||||
|
import static io.javalin.apibuilder.ApiBuilder.post;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** endpoints and handlers for deal with record scripts
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QJavalinScriptsHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Define routes under the basic /data/${table}/${primaryKey} path - e.g.,
|
||||||
|
** record-specific script routes.
|
||||||
|
*******************************************************************************/
|
||||||
|
public static void defineRecordRoutes()
|
||||||
|
{
|
||||||
|
get("/developer", QJavalinScriptsHandler::getRecordDeveloperMode);
|
||||||
|
post("/developer/associatedScript/{fieldName}", QJavalinScriptsHandler::storeRecordAssociatedScript);
|
||||||
|
get("/developer/associatedScript/{fieldName}/{scriptRevisionId}/logs", QJavalinScriptsHandler::getAssociatedScriptLogs);
|
||||||
|
post("/developer/associatedScript/{fieldName}/test", QJavalinScriptsHandler::testAssociatedScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void getRecordDeveloperMode(Context context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String tableName = context.pathParam("table");
|
||||||
|
QTableMetaData table = QJavalinImplementation.qInstance.getTable(tableName);
|
||||||
|
String primaryKey = context.pathParam("primaryKey");
|
||||||
|
GetInput getInput = new GetInput(QJavalinImplementation.qInstance);
|
||||||
|
|
||||||
|
QJavalinImplementation.setupSession(context, getInput);
|
||||||
|
getInput.setTableName(tableName);
|
||||||
|
getInput.setShouldGenerateDisplayValues(true);
|
||||||
|
getInput.setShouldTranslatePossibleValues(true);
|
||||||
|
|
||||||
|
// todo - validate that the primary key is of the proper type (e.g,. not a string for an id field)
|
||||||
|
// and throw a 400-series error (tell the user bad-request), rather than, we're doing a 500 (server error)
|
||||||
|
|
||||||
|
getInput.setPrimaryKey(primaryKey);
|
||||||
|
|
||||||
|
GetAction getAction = new GetAction();
|
||||||
|
GetOutput getOutput = getAction.execute(getInput);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// throw a not found error if the record isn't found //
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
QRecord record = getOutput.getRecord();
|
||||||
|
if(record == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("Could not find " + table.getLabel() + " with "
|
||||||
|
+ table.getFields().get(table.getPrimaryKeyField()).getLabel() + " of " + primaryKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Serializable> rs = new HashMap<>();
|
||||||
|
rs.put("record", record);
|
||||||
|
|
||||||
|
ArrayList<HashMap<String, Serializable>> associatedScripts = new ArrayList<>();
|
||||||
|
rs.put("associatedScripts", associatedScripts);
|
||||||
|
|
||||||
|
Map<Serializable, QRecord> scriptTypeMap = GeneralProcessUtils.loadTableToMap(getInput, ScriptType.TABLE_NAME, "id");
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// process each associated script type for the table //
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
QInstanceEnricher qInstanceEnricher = new QInstanceEnricher(QJavalinImplementation.qInstance);
|
||||||
|
for(AssociatedScript associatedScript : CollectionUtils.nonNullList(table.getAssociatedScripts()))
|
||||||
|
{
|
||||||
|
HashMap<String, Serializable> thisScriptData = new HashMap<>();
|
||||||
|
associatedScripts.add(thisScriptData);
|
||||||
|
thisScriptData.put("associatedScript", associatedScript);
|
||||||
|
thisScriptData.put("scriptType", scriptTypeMap.get(associatedScript.getScriptTypeId()));
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// load the associated script and current revision from the record //
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
String fieldName = associatedScript.getFieldName();
|
||||||
|
Serializable scriptId = record.getValue(fieldName);
|
||||||
|
if(scriptId != null)
|
||||||
|
{
|
||||||
|
GetInput getScriptInput = new GetInput(QJavalinImplementation.qInstance);
|
||||||
|
QJavalinImplementation.setupSession(context, getScriptInput);
|
||||||
|
getScriptInput.setTableName("script");
|
||||||
|
getScriptInput.setPrimaryKey(scriptId);
|
||||||
|
GetOutput getScriptOutput = new GetAction().execute(getScriptInput);
|
||||||
|
if(getScriptOutput.getRecord() != null)
|
||||||
|
{
|
||||||
|
thisScriptData.put("script", getScriptOutput.getRecord());
|
||||||
|
|
||||||
|
QueryInput queryInput = new QueryInput(QJavalinImplementation.qInstance);
|
||||||
|
QJavalinImplementation.setupSession(context, queryInput);
|
||||||
|
queryInput.setTableName("scriptRevision");
|
||||||
|
queryInput.setFilter(new QQueryFilter()
|
||||||
|
.withCriteria(new QFilterCriteria("scriptId", QCriteriaOperator.EQUALS, List.of(getScriptOutput.getRecord().getValue("id"))))
|
||||||
|
.withOrderBy(new QFilterOrderBy("id", false))
|
||||||
|
);
|
||||||
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
thisScriptData.put("scriptRevisions", new ArrayList<>(queryOutput.getRecords()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// load testing info about the script type, if available //
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
QCodeReference scriptTesterCodeRef = associatedScript.getScriptTester();
|
||||||
|
if(scriptTesterCodeRef != null)
|
||||||
|
{
|
||||||
|
TestScriptActionInterface scriptTester = QCodeLoader.getAdHoc(TestScriptActionInterface.class, scriptTesterCodeRef);
|
||||||
|
thisScriptData.put("testInputFields", enrichFieldsToArrayList(qInstanceEnricher, scriptTester.getTestInputFields()));
|
||||||
|
thisScriptData.put("testOutputFields", enrichFieldsToArrayList(qInstanceEnricher, scriptTester.getTestOutputFields()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.result(JsonUtils.toJson(rs));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
QJavalinImplementation.handleException(context, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static Serializable enrichFieldsToArrayList(QInstanceEnricher qInstanceEnricher, List<QFieldMetaData> fields)
|
||||||
|
{
|
||||||
|
ArrayList<QFieldMetaData> rs = new ArrayList<>();
|
||||||
|
|
||||||
|
if(CollectionUtils.nullSafeIsEmpty(fields))
|
||||||
|
{
|
||||||
|
return (rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(QFieldMetaData field : fields)
|
||||||
|
{
|
||||||
|
qInstanceEnricher.enrichField(field);
|
||||||
|
rs.add(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static void getAssociatedScriptLogs(Context context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String scriptRevisionId = context.pathParam("scriptRevisionId");
|
||||||
|
|
||||||
|
QueryInput queryInput = new QueryInput(QJavalinImplementation.qInstance);
|
||||||
|
QJavalinImplementation.setupSession(context, queryInput);
|
||||||
|
queryInput.setTableName("scriptLog");
|
||||||
|
queryInput.setFilter(new QQueryFilter()
|
||||||
|
.withCriteria(new QFilterCriteria("scriptRevisionId", QCriteriaOperator.EQUALS, List.of(scriptRevisionId)))
|
||||||
|
.withOrderBy(new QFilterOrderBy("id", false))
|
||||||
|
);
|
||||||
|
queryInput.setLimit(100);
|
||||||
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
|
||||||
|
if(CollectionUtils.nullSafeHasContents(queryOutput.getRecords()))
|
||||||
|
{
|
||||||
|
GeneralProcessUtils.addForeignRecordsListToRecordList(queryInput, queryOutput.getRecords(), "id", "scriptLogLine", "scriptLogId");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Serializable> rs = new HashMap<>();
|
||||||
|
rs.put("scriptLogRecords", new ArrayList<>(queryOutput.getRecords()));
|
||||||
|
|
||||||
|
context.result(JsonUtils.toJson(rs));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
QJavalinImplementation.handleException(context, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void storeRecordAssociatedScript(Context context)
|
||||||
|
{
|
||||||
|
context.contentType(ContentType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StoreAssociatedScriptInput input = new StoreAssociatedScriptInput(QJavalinImplementation.qInstance);
|
||||||
|
QJavalinImplementation.setupSession(context, input);
|
||||||
|
input.setCode(context.formParam("contents"));
|
||||||
|
input.setCommitMessage(context.formParam("commitMessage"));
|
||||||
|
input.setFieldName(context.pathParam("fieldName"));
|
||||||
|
input.setTableName(context.pathParam("table"));
|
||||||
|
input.setRecordPrimaryKey(context.pathParam("primaryKey"));
|
||||||
|
|
||||||
|
StoreAssociatedScriptOutput output = new StoreAssociatedScriptOutput();
|
||||||
|
|
||||||
|
StoreAssociatedScriptAction storeAssociatedScriptAction = new StoreAssociatedScriptAction();
|
||||||
|
storeAssociatedScriptAction.run(input, output);
|
||||||
|
|
||||||
|
context.result(JsonUtils.toJson(output));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
QJavalinImplementation.handleException(context, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void testAssociatedScript(Context context)
|
||||||
|
{
|
||||||
|
context.contentType(ContentType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TestScriptInput input = new TestScriptInput(QJavalinImplementation.qInstance);
|
||||||
|
QJavalinImplementation.setupSession(context, input);
|
||||||
|
|
||||||
|
// todo delete? input.setRecordPrimaryKey(context.pathParam("primaryKey"));
|
||||||
|
Map<String, Serializable> inputValues = new HashMap<>();
|
||||||
|
input.setInputValues(inputValues);
|
||||||
|
|
||||||
|
String tableName = context.pathParam("table");
|
||||||
|
String fieldName = context.pathParam("fieldName");
|
||||||
|
QTableMetaData table = QJavalinImplementation.qInstance.getTable(tableName);
|
||||||
|
|
||||||
|
Optional<AssociatedScript> optionalAssociatedScript = table.getAssociatedScripts().stream().filter(as -> as.getFieldName().equals(fieldName)).findFirst();
|
||||||
|
if(optionalAssociatedScript.isEmpty())
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("No associated script was found for field " + fieldName + " on table " + tableName);
|
||||||
|
}
|
||||||
|
AssociatedScript associatedScript = optionalAssociatedScript.get();
|
||||||
|
|
||||||
|
QCodeReference scriptTesterCodeRef = associatedScript.getScriptTester();
|
||||||
|
if(scriptTesterCodeRef == null)
|
||||||
|
{
|
||||||
|
throw (new IllegalArgumentException("This scriptType cannot be tested, as it does not define a scriptTester codeReference."));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Map.Entry<String, List<String>> entry : context.formParamMap().entrySet())
|
||||||
|
{
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue().get(0);
|
||||||
|
|
||||||
|
if(key.equals("code"))
|
||||||
|
{
|
||||||
|
input.setCodeReference(new QCodeReference().withInlineCode(value).withCodeType(QCodeType.JAVA_SCRIPT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputValues.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestScriptActionInterface scriptTester = QCodeLoader.getAdHoc(TestScriptActionInterface.class, scriptTesterCodeRef);
|
||||||
|
TestScriptOutput output = new TestScriptOutput();
|
||||||
|
scriptTester.execute(input, output);
|
||||||
|
|
||||||
|
context.result(JsonUtils.toJson(output));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
QJavalinImplementation.handleException(context, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,23 +26,9 @@ import java.io.Serializable;
|
|||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
import kong.unirest.HttpResponse;
|
import kong.unirest.HttpResponse;
|
||||||
import kong.unirest.Unirest;
|
import kong.unirest.Unirest;
|
||||||
@ -630,135 +616,4 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
|||||||
assertEquals(5, jsonObject.getJSONArray("options").getJSONObject(1).getInt("id"));
|
assertEquals(5, jsonObject.getJSONArray("options").getJSONObject(1).getInt("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
void testGetRecordDeveloperMode() throws QException
|
|
||||||
{
|
|
||||||
UpdateInput updateInput = new UpdateInput(TestUtils.defineInstance());
|
|
||||||
updateInput.setSession(new QSession());
|
|
||||||
updateInput.setTableName("person");
|
|
||||||
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("testScriptId", 47)));
|
|
||||||
new UpdateAction().execute(updateInput);
|
|
||||||
|
|
||||||
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
|
||||||
insertInput.setSession(new QSession());
|
|
||||||
insertInput.setTableName("script");
|
|
||||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 47).withValue("currentScriptRevisionId", 100)));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
insertInput.setTableName("scriptRevision");
|
|
||||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1000).withValue("scriptId", 47).withValue("content", "var i;")));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/developer").asString();
|
|
||||||
assertEquals(200, response.getStatus());
|
|
||||||
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
|
||||||
System.out.println(jsonObject.toString(3));
|
|
||||||
assertNotNull(jsonObject);
|
|
||||||
assertNotNull(jsonObject.getJSONObject("record"));
|
|
||||||
assertEquals("Darin", jsonObject.getJSONObject("record").getJSONObject("values").getString("firstName"));
|
|
||||||
assertEquals("Darin", jsonObject.getJSONObject("record").getJSONObject("displayValues").getString("firstName"));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("associatedScripts"));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONArray("scriptRevisions"));
|
|
||||||
assertEquals("var i;", jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONArray("scriptRevisions").getJSONObject(0).getJSONObject("values").getString("content"));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("script"));
|
|
||||||
assertEquals(100, jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("script").getJSONObject("values").getInt("currentScriptRevisionId"));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("associatedScript"));
|
|
||||||
assertEquals("testScriptId", jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("associatedScript").getString("fieldName"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
void testStoreRecordAssociatedScript() throws QException
|
|
||||||
{
|
|
||||||
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
|
||||||
insertInput.setSession(new QSession());
|
|
||||||
insertInput.setTableName("scriptType");
|
|
||||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("name", "Test")));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId")
|
|
||||||
.field("contents", "var j = 0;")
|
|
||||||
.field("commitMessage", "Javalin Commit")
|
|
||||||
.asString();
|
|
||||||
|
|
||||||
QueryInput queryInput = new QueryInput(TestUtils.defineInstance());
|
|
||||||
queryInput.setSession(new QSession());
|
|
||||||
queryInput.setTableName("scriptRevision");
|
|
||||||
queryInput.setFilter(new QQueryFilter()
|
|
||||||
.withCriteria(new QFilterCriteria("contents", QCriteriaOperator.EQUALS, List.of("var j = 0;")))
|
|
||||||
.withCriteria(new QFilterCriteria("commitMessage", QCriteriaOperator.EQUALS, List.of("Javalin Commit")))
|
|
||||||
);
|
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
|
||||||
assertEquals(1, queryOutput.getRecords().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
void testTestAssociatedScript() throws QException
|
|
||||||
{
|
|
||||||
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
|
||||||
insertInput.setSession(new QSession());
|
|
||||||
insertInput.setTableName("scriptType");
|
|
||||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("name", "Test")));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId/test")
|
|
||||||
.field("code", "var j = 0;")
|
|
||||||
.field("scriptTypeId", "1")
|
|
||||||
.field("x", "47")
|
|
||||||
.asString();
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
// todo - assertions after implemented //
|
|
||||||
/////////////////////////////////////////
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
void testGetAssociatedScriptLogs() throws QException
|
|
||||||
{
|
|
||||||
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
|
||||||
insertInput.setSession(new QSession());
|
|
||||||
insertInput.setTableName("scriptLog");
|
|
||||||
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("output", "testOutput").withValue("scriptRevisionId", 100)));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
insertInput.setTableName("scriptLogLine");
|
|
||||||
insertInput.setRecords(List.of(
|
|
||||||
new QRecord().withValue("scriptLogId", 1).withValue("text", "line one"),
|
|
||||||
new QRecord().withValue("scriptLogId", 1).withValue("text", "line two")
|
|
||||||
));
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
|
|
||||||
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId/100/logs").asString();
|
|
||||||
assertEquals(200, response.getStatus());
|
|
||||||
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
|
||||||
assertNotNull(jsonObject.getJSONArray("scriptLogRecords"));
|
|
||||||
assertEquals(1, jsonObject.getJSONArray("scriptLogRecords").length());
|
|
||||||
assertNotNull(jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values"));
|
|
||||||
assertEquals("testOutput", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getString("output"));
|
|
||||||
assertNotNull(jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine"));
|
|
||||||
assertEquals(2, jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").length());
|
|
||||||
assertEquals("line one", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").getJSONObject(0).getJSONObject("values").getString("text"));
|
|
||||||
assertEquals("line two", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").getJSONObject(1).getJSONObject("values").getString("text"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.javalin;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
|
import kong.unirest.HttpResponse;
|
||||||
|
import kong.unirest.Unirest;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for the javalin scripts handler methods.
|
||||||
|
*******************************************************************************/
|
||||||
|
class QJavalinScriptsHandlerTest extends QJavalinTestBase
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetRecordDeveloperMode() throws QException
|
||||||
|
{
|
||||||
|
UpdateInput updateInput = new UpdateInput(TestUtils.defineInstance());
|
||||||
|
updateInput.setSession(new QSession());
|
||||||
|
updateInput.setTableName("person");
|
||||||
|
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("testScriptId", 47)));
|
||||||
|
new UpdateAction().execute(updateInput);
|
||||||
|
|
||||||
|
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
||||||
|
insertInput.setSession(new QSession());
|
||||||
|
insertInput.setTableName("script");
|
||||||
|
insertInput.setRecords(List.of(new QRecord().withValue("id", 47).withValue("currentScriptRevisionId", 100)));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
insertInput.setTableName("scriptRevision");
|
||||||
|
insertInput.setRecords(List.of(new QRecord().withValue("id", 1000).withValue("scriptId", 47).withValue("content", "var i;")));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/developer").asString();
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
System.out.println(jsonObject.toString(3));
|
||||||
|
assertNotNull(jsonObject);
|
||||||
|
assertNotNull(jsonObject.getJSONObject("record"));
|
||||||
|
assertEquals("Darin", jsonObject.getJSONObject("record").getJSONObject("values").getString("firstName"));
|
||||||
|
assertEquals("Darin", jsonObject.getJSONObject("record").getJSONObject("displayValues").getString("firstName"));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("associatedScripts"));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONArray("scriptRevisions"));
|
||||||
|
assertEquals("var i;", jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONArray("scriptRevisions").getJSONObject(0).getJSONObject("values").getString("content"));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("script"));
|
||||||
|
assertEquals(100, jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("script").getJSONObject("values").getInt("currentScriptRevisionId"));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("associatedScript"));
|
||||||
|
assertEquals("testScriptId", jsonObject.getJSONArray("associatedScripts").getJSONObject(0).getJSONObject("associatedScript").getString("fieldName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testStoreRecordAssociatedScript() throws QException
|
||||||
|
{
|
||||||
|
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
||||||
|
insertInput.setSession(new QSession());
|
||||||
|
insertInput.setTableName("scriptType");
|
||||||
|
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("name", "Test")));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId")
|
||||||
|
.field("contents", "var j = 0;")
|
||||||
|
.field("commitMessage", "Javalin Commit")
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
QueryInput queryInput = new QueryInput(TestUtils.defineInstance());
|
||||||
|
queryInput.setSession(new QSession());
|
||||||
|
queryInput.setTableName("scriptRevision");
|
||||||
|
queryInput.setFilter(new QQueryFilter()
|
||||||
|
.withCriteria(new QFilterCriteria("contents", QCriteriaOperator.EQUALS, List.of("var j = 0;")))
|
||||||
|
.withCriteria(new QFilterCriteria("commitMessage", QCriteriaOperator.EQUALS, List.of("Javalin Commit")))
|
||||||
|
);
|
||||||
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
assertEquals(1, queryOutput.getRecords().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testTestAssociatedScript() throws QException
|
||||||
|
{
|
||||||
|
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
||||||
|
insertInput.setSession(new QSession());
|
||||||
|
insertInput.setTableName("scriptType");
|
||||||
|
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("name", "Test")));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId/test")
|
||||||
|
.field("code", """
|
||||||
|
// output.setMessage(`${input.getName()} is ${input.getAge()} years old.`);
|
||||||
|
output.setMessage("I am " + input.getName());
|
||||||
|
return (output);
|
||||||
|
""")
|
||||||
|
.field("scriptTypeId", "1")
|
||||||
|
.field("name", "Tim")
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
assertEquals("I am Tim", jsonObject.getJSONObject("outputObject").getString("message"));
|
||||||
|
assertNotNull(jsonObject.getJSONObject("scriptLog"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetAssociatedScriptLogs() throws QException
|
||||||
|
{
|
||||||
|
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
||||||
|
insertInput.setSession(new QSession());
|
||||||
|
insertInput.setTableName("scriptLog");
|
||||||
|
insertInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("output", "testOutput").withValue("scriptRevisionId", 100)));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
insertInput.setTableName("scriptLogLine");
|
||||||
|
insertInput.setRecords(List.of(
|
||||||
|
new QRecord().withValue("scriptLogId", 1).withValue("text", "line one"),
|
||||||
|
new QRecord().withValue("scriptLogId", 1).withValue("text", "line two")
|
||||||
|
));
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/1/developer/associatedScript/testScriptId/100/logs").asString();
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
assertNotNull(jsonObject.getJSONArray("scriptLogRecords"));
|
||||||
|
assertEquals(1, jsonObject.getJSONArray("scriptLogRecords").length());
|
||||||
|
assertNotNull(jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values"));
|
||||||
|
assertEquals("testOutput", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getString("output"));
|
||||||
|
assertNotNull(jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine"));
|
||||||
|
assertEquals(2, jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").length());
|
||||||
|
assertEquals("line one", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").getJSONObject(0).getJSONObject("values").getString("text"));
|
||||||
|
assertEquals("line two", jsonObject.getJSONArray("scriptLogRecords").getJSONObject(0).getJSONObject("values").getJSONArray("scriptLogLine").getJSONObject(1).getJSONObject("values").getString("text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.javalin;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptActionInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class TestScriptAction implements TestScriptActionInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void setupTestScriptInput(TestScriptInput testScriptInput, ExecuteCodeInput executeCodeInput)
|
||||||
|
{
|
||||||
|
SampleTestInput sampleTestInput = new SampleTestInput();
|
||||||
|
sampleTestInput.setName(ValueUtils.getValueAsString(testScriptInput.getInputValues().get("name")));
|
||||||
|
sampleTestInput.setAge(ValueUtils.getValueAsInteger(testScriptInput.getInputValues().get("age")));
|
||||||
|
executeCodeInput.setInput(Map.of("input", sampleTestInput));
|
||||||
|
|
||||||
|
executeCodeInput.getContext().put("output", new SampleTestOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QFieldMetaData> getTestInputFields()
|
||||||
|
{
|
||||||
|
return List.of(
|
||||||
|
new QFieldMetaData("name", QFieldType.STRING),
|
||||||
|
new QFieldMetaData("age", QFieldType.INTEGER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public List<QFieldMetaData> getTestOutputFields()
|
||||||
|
{
|
||||||
|
return List.of(new QFieldMetaData("message", QFieldType.STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleTestInput implements Serializable
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for age
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer getAge()
|
||||||
|
{
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for age
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAge(Integer age)
|
||||||
|
{
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class SampleTestOutput implements Serializable
|
||||||
|
{
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for message
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for message
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setMessage(String message)
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -227,7 +227,8 @@ public class TestUtils
|
|||||||
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER).withBackendName("test_script_id"))
|
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER).withBackendName("test_script_id"))
|
||||||
.withAssociatedScript(new AssociatedScript()
|
.withAssociatedScript(new AssociatedScript()
|
||||||
.withFieldName("testScriptId")
|
.withFieldName("testScriptId")
|
||||||
.withScriptTypeId(1));
|
.withScriptTypeId(1)
|
||||||
|
.withScriptTester(new QCodeReference(TestScriptAction.class, QCodeUsage.SCRIPT_TESTER)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user