2024-05-27 06:15:10 +00:00
import {
defaultAffectedJSObjects ,
evalQueueBuffer ,
evaluateTreeSaga ,
} from "./EvaluationsSaga" ;
2024-12-13 04:14:19 +00:00
import { evalWorker } from "utils/workerInstances" ;
2024-05-09 11:47:58 +00:00
import { expectSaga } from "redux-saga-test-plan" ;
2024-08-06 14:52:22 +00:00
import { EVAL_WORKER_ACTIONS } from "ee/workers/Evaluation/evalWorkerActions" ;
2024-05-09 11:47:58 +00:00
import { select } from "redux-saga/effects" ;
import { getMetaWidgets , getWidgets , getWidgetsMeta } from "./selectors" ;
2024-08-06 14:52:22 +00:00
import { getAllActionValidationConfig } from "ee//selectors/entitiesSelector" ;
2024-05-09 11:47:58 +00:00
import { getSelectedAppTheme } from "selectors/appThemingSelectors" ;
2024-08-06 14:52:22 +00:00
import { getAppMode } from "ee/selectors/applicationSelectors" ;
2024-05-09 11:47:58 +00:00
import * as log from "loglevel" ;
2024-05-27 06:15:10 +00:00
2025-01-10 04:51:54 +00:00
import type { ReduxAction } from "actions/ReduxActionTypes" ;
2024-05-27 06:15:10 +00:00
import {
ReduxActionErrorTypes ,
ReduxActionTypes ,
2024-08-06 14:52:22 +00:00
} from "ee/constants/ReduxActionConstants" ;
2024-05-27 06:15:10 +00:00
import { fetchPluginFormConfigsSuccess } from "actions/pluginActions" ;
import { createJSCollectionSuccess } from "actions/jsActionActions" ;
2024-10-15 15:35:39 +00:00
import { getInstanceId } from "ee/selectors/tenantSelectors" ;
import {
getApplicationLastDeployedAt ,
getCurrentApplicationId ,
getCurrentPageId ,
} from "selectors/editorSelectors" ;
2024-12-30 06:48:19 +00:00
import { updateActionData } from "actions/pluginActionActions" ;
2024-10-15 15:35:39 +00:00
2024-05-09 11:47:58 +00:00
jest . mock ( "loglevel" ) ;
describe ( "evaluateTreeSaga" , ( ) = > {
afterAll ( ( ) = > {
jest . unmock ( "loglevel" ) ;
} ) ;
test ( "should set 'shouldRespondWithLogs'to evaluations when the log level is debug" , async ( ) = > {
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-09 11:47:58 +00:00
( log . getLevel as any ) . mockReturnValue ( log . levels . DEBUG ) ;
const unEvalAndConfigTree = { unEvalTree : { } , configTree : { } } ;
2024-09-18 16:35:28 +00:00
2024-05-09 11:47:58 +00:00
return expectSaga ( evaluateTreeSaga , unEvalAndConfigTree )
. provide ( [
[ select ( getAllActionValidationConfig ) , { } ] ,
[ select ( getWidgets ) , { } ] ,
[ select ( getMetaWidgets ) , { } ] ,
[ select ( getSelectedAppTheme ) , { } ] ,
[ select ( getAppMode ) , false ] ,
[ select ( getWidgetsMeta ) , { } ] ,
2024-10-15 15:35:39 +00:00
[ select ( getInstanceId ) , "instanceId" ] ,
[ select ( getCurrentApplicationId ) , "applicationId" ] ,
[ select ( getCurrentPageId ) , "pageId" ] ,
[
select ( getApplicationLastDeployedAt ) ,
new Date ( "11 September 2024" ) . toISOString ( ) ,
] ,
2024-05-09 11:47:58 +00:00
] )
. call ( evalWorker . request , EVAL_WORKER_ACTIONS . EVAL_TREE , {
2024-10-15 15:35:39 +00:00
cacheProps : {
instanceId : "instanceId" ,
appId : "applicationId" ,
pageId : "pageId" ,
appMode : false ,
timestamp : new Date ( "11 September 2024" ) . toISOString ( ) ,
} ,
2024-05-09 11:47:58 +00:00
unevalTree : unEvalAndConfigTree ,
widgetTypeConfigMap : undefined ,
widgets : { } ,
theme : { } ,
shouldReplay : true ,
allActionValidationConfig : { } ,
forceEvaluation : false ,
metaWidgets : { } ,
appMode : false ,
widgetsMeta : { } ,
shouldRespondWithLogs : true ,
2024-05-27 06:15:10 +00:00
affectedJSObjects : { ids : [ ] , isAllAffected : false } ,
2024-05-09 11:47:58 +00:00
} )
. run ( ) ;
} ) ;
test ( "should set 'shouldRespondWithLogs' to false when the log level is not debug" , async ( ) = > {
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-09 11:47:58 +00:00
( log . getLevel as any ) . mockReturnValue ( log . levels . INFO ) ;
const unEvalAndConfigTree = { unEvalTree : { } , configTree : { } } ;
2024-09-18 16:35:28 +00:00
2024-05-09 11:47:58 +00:00
return expectSaga ( evaluateTreeSaga , unEvalAndConfigTree )
. provide ( [
[ select ( getAllActionValidationConfig ) , { } ] ,
[ select ( getWidgets ) , { } ] ,
[ select ( getMetaWidgets ) , { } ] ,
[ select ( getSelectedAppTheme ) , { } ] ,
[ select ( getAppMode ) , false ] ,
[ select ( getWidgetsMeta ) , { } ] ,
2024-10-15 15:35:39 +00:00
[ select ( getInstanceId ) , "instanceId" ] ,
[ select ( getCurrentApplicationId ) , "applicationId" ] ,
[ select ( getCurrentPageId ) , "pageId" ] ,
[
select ( getApplicationLastDeployedAt ) ,
new Date ( "11 September 2024" ) . toISOString ( ) ,
] ,
2024-05-09 11:47:58 +00:00
] )
. call ( evalWorker . request , EVAL_WORKER_ACTIONS . EVAL_TREE , {
2024-10-15 15:35:39 +00:00
cacheProps : {
instanceId : "instanceId" ,
appId : "applicationId" ,
pageId : "pageId" ,
appMode : false ,
timestamp : new Date ( "11 September 2024" ) . toISOString ( ) ,
} ,
2024-05-09 11:47:58 +00:00
unevalTree : unEvalAndConfigTree ,
widgetTypeConfigMap : undefined ,
widgets : { } ,
theme : { } ,
shouldReplay : true ,
allActionValidationConfig : { } ,
forceEvaluation : false ,
metaWidgets : { } ,
appMode : false ,
widgetsMeta : { } ,
shouldRespondWithLogs : false ,
2024-05-27 06:15:10 +00:00
affectedJSObjects : { ids : [ ] , isAllAffected : false } ,
2024-05-09 11:47:58 +00:00
} )
. run ( ) ;
} ) ;
2024-05-27 06:15:10 +00:00
test ( "should propagate affectedJSObjects property to evaluation action" , async ( ) = > {
const unEvalAndConfigTree = { unEvalTree : { } , configTree : { } } ;
const affectedJSObjects = {
isAllAffected : false ,
ids : [ "1" , "2" ] ,
} ;
return expectSaga (
evaluateTreeSaga ,
unEvalAndConfigTree ,
[ ] ,
undefined ,
undefined ,
undefined ,
affectedJSObjects ,
)
. provide ( [
[ select ( getAllActionValidationConfig ) , { } ] ,
[ select ( getWidgets ) , { } ] ,
[ select ( getMetaWidgets ) , { } ] ,
[ select ( getSelectedAppTheme ) , { } ] ,
[ select ( getAppMode ) , false ] ,
[ select ( getWidgetsMeta ) , { } ] ,
2024-10-15 15:35:39 +00:00
[ select ( getInstanceId ) , "instanceId" ] ,
[ select ( getCurrentApplicationId ) , "applicationId" ] ,
[ select ( getCurrentPageId ) , "pageId" ] ,
[
select ( getApplicationLastDeployedAt ) ,
new Date ( "11 September 2024" ) . toISOString ( ) ,
] ,
2024-05-27 06:15:10 +00:00
] )
. call ( evalWorker . request , EVAL_WORKER_ACTIONS . EVAL_TREE , {
2024-10-15 15:35:39 +00:00
cacheProps : {
instanceId : "instanceId" ,
appId : "applicationId" ,
pageId : "pageId" ,
appMode : false ,
timestamp : new Date ( "11 September 2024" ) . toISOString ( ) ,
} ,
2024-05-27 06:15:10 +00:00
unevalTree : unEvalAndConfigTree ,
widgetTypeConfigMap : undefined ,
widgets : { } ,
theme : { } ,
shouldReplay : true ,
allActionValidationConfig : { } ,
forceEvaluation : false ,
metaWidgets : { } ,
appMode : false ,
widgetsMeta : { } ,
shouldRespondWithLogs : false ,
affectedJSObjects ,
} )
. run ( ) ;
} ) ;
} ) ;
describe ( "evalQueueBuffer" , ( ) = > {
test ( "should return a buffered action with the default affectedJSObjects state for an action which does not have affectedJSObjects associated to it" , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
// this action does not generate an affectedJSObject
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( fetchPluginFormConfigsSuccess ( { } as any ) ) ;
const bufferedAction = buffer . take ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
expect ( bufferedAction ) . toEqual ( {
2024-12-30 06:48:19 +00:00
actionDataPayloadConsolidated : [ ] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : false ,
2024-05-27 06:15:10 +00:00
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : defaultAffectedJSObjects ,
postEvalActions : [ ] ,
} ) ;
} ) ;
test ( "should club all JS actions affectedJSObjects's ids" , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
2024-09-18 16:35:28 +00:00
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( createJSCollectionSuccess ( { id : "1" } as any ) ) ;
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( createJSCollectionSuccess ( { id : "2" } as any ) ) ;
const bufferedAction = buffer . take ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
expect ( bufferedAction ) . toEqual ( {
2024-12-30 06:48:19 +00:00
actionDataPayloadConsolidated : [ ] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : false ,
2024-05-27 06:15:10 +00:00
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : { ids : [ "1" , "2" ] , isAllAffected : false } ,
postEvalActions : [ ] ,
} ) ;
} ) ;
test ( "should return all JS actions that have changed when there is a pending action which affects all JS actions " , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
2024-09-18 16:35:28 +00:00
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( createJSCollectionSuccess ( { id : "1" } as any ) ) ;
// this action triggers an isAllAffected flag
buffer . put ( {
type : ReduxActionErrorTypes . FETCH_JS_ACTIONS_ERROR ,
} as ReduxAction < unknown > ) ;
// queue is not empty
expect ( buffer . isEmpty ( ) ) . not . toBeTruthy ( ) ;
const bufferedAction = buffer . take ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
expect ( bufferedAction ) . toEqual ( {
2024-12-30 06:48:19 +00:00
actionDataPayloadConsolidated : [ ] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : false ,
2024-05-27 06:15:10 +00:00
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : { ids : [ ] , isAllAffected : true } ,
postEvalActions : [ ] ,
} ) ;
expect ( buffer . isEmpty ( ) ) . toBeTruthy ( ) ;
} ) ;
test ( "should reset the collectedAffectedJSObjects after the buffered action has been dequeued and the subsequent actions should have the defaultAffectedJSObjects" , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
2024-09-18 16:35:28 +00:00
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( createJSCollectionSuccess ( { id : "1" } as any ) ) ;
const bufferedAction = buffer . take ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
expect ( bufferedAction ) . toEqual ( {
2024-12-30 06:48:19 +00:00
actionDataPayloadConsolidated : [ ] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : false ,
2024-05-27 06:15:10 +00:00
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : { ids : [ "1" ] , isAllAffected : false } ,
postEvalActions : [ ] ,
} ) ;
expect ( buffer . isEmpty ( ) ) . toBeTruthy ( ) ;
// this action does not generate an affectedJSObject, So the subsequent buffered action should have default affectedJSObjects
2024-07-31 15:41:28 +00:00
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-05-27 06:15:10 +00:00
buffer . put ( fetchPluginFormConfigsSuccess ( { id : "1" } as any ) ) ;
const bufferedActionsWithDefaultAffectedJSObjects = buffer . take ( ) ;
2024-09-18 16:35:28 +00:00
2024-05-27 06:15:10 +00:00
expect ( bufferedActionsWithDefaultAffectedJSObjects ) . toEqual ( {
2024-12-30 06:48:19 +00:00
actionDataPayloadConsolidated : [ ] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : false ,
2024-05-27 06:15:10 +00:00
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : defaultAffectedJSObjects ,
postEvalActions : [ ] ,
} ) ;
} ) ;
2024-12-30 06:48:19 +00:00
test ( "should debounce UPDATE_ACTION_DATA actions together when the buffer is busy" , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
buffer . put (
updateActionData ( [
{
entityName : "widget1" ,
dataPath : "data" ,
data : { a : 1 } ,
dataPathRef : "" ,
} ,
] ) ,
) ;
buffer . put (
updateActionData ( [
{
entityName : "widget2" ,
dataPath : "data" ,
data : { a : 2 } ,
dataPathRef : "" ,
} ,
] ) ,
) ;
const bufferedActionsWithDefaultAffectedJSObjects = buffer . take ( ) ;
expect ( bufferedActionsWithDefaultAffectedJSObjects ) . toEqual ( {
actionDataPayloadConsolidated : [
{
data : {
a : 1 ,
} ,
dataPath : "data" ,
dataPathRef : "" ,
entityName : "widget1" ,
} ,
{
data : {
a : 2 ,
} ,
dataPath : "data" ,
dataPathRef : "" ,
entityName : "widget2" ,
} ,
] ,
hasBufferedAction : false ,
hasDebouncedHandleUpdate : true ,
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : defaultAffectedJSObjects ,
postEvalActions : [ ] ,
} ) ;
} ) ;
test ( "should be able to debounce UPDATE_ACTION_DATA actions and BUFFERED_ACTION together when the buffer is busy" , ( ) = > {
const buffer = evalQueueBuffer ( ) ;
buffer . put (
updateActionData ( [
{
entityName : "widget1" ,
dataPath : "data" ,
data : { a : 1 } ,
dataPathRef : "" ,
} ,
] ) ,
) ;
buffer . put (
updateActionData ( [
{
entityName : "widget2" ,
dataPath : "data" ,
data : { a : 2 } ,
dataPathRef : "" ,
} ,
] ) ,
) ;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
buffer . put ( createJSCollectionSuccess ( { id : "1" } as any ) ) ;
const bufferedActionsWithDefaultAffectedJSObjects = buffer . take ( ) ;
expect ( bufferedActionsWithDefaultAffectedJSObjects ) . toEqual ( {
actionDataPayloadConsolidated : [
{
data : {
a : 1 ,
} ,
dataPath : "data" ,
dataPathRef : "" ,
entityName : "widget1" ,
} ,
{
data : {
a : 2 ,
} ,
dataPath : "data" ,
dataPathRef : "" ,
entityName : "widget2" ,
} ,
] ,
hasBufferedAction : true ,
hasDebouncedHandleUpdate : true ,
type : ReduxActionTypes . BUFFERED_ACTION ,
affectedJSObjects : { ids : [ "1" ] , isAllAffected : false } ,
postEvalActions : [ ] ,
} ) ;
} ) ;
2024-05-09 11:47:58 +00:00
} ) ;