Compare commits

...
Author SHA1 Message Date
james.maesandClaude Fable 5.1 433523ca5b fix(processes): keep SendTestEventToWebhook's records past its input screen
The input form sat at step 0, before the streamed-ETL preview step. The
records chosen when the process starts reach only the steps of that first
run, and the preview step is what keeps them (as queryFilterJson) for the
later steps; with the form first, the run stopped before any backend step,
so submitting the form failed with "No records were selected for running
this process" from every UI API client.

The form now follows the preview step. Its value is read only by the load
step. SendTestEventToWebhookProcessTest runs the process the way a UI does
(records at init, none on the continuation) and failed before this change.

Refs QRun-IO/qqq#1361

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-01 05:16:46 -06:00
2 changed files with 100 additions and 1 deletions

No files matched your search

@@ -73,7 +73,15 @@ public class SendTestEventToWebhookProcessMetaDataProducer extends MetaDataProdu
))
.getProcessMetaData();
processMetaData.withStep(0, new QFrontendStepMetaData()
//////////////////////////////////////////////////////////////////////////
// the input screen goes after the first backend (preview) step, not //
// before it: the records chosen when the process starts reach only //
// the steps of that first run, and the preview step is what keeps //
// them (as queryFilterJson) for the later steps. As step 0 the screen //
// stopped the first run before any backend step, so the records were //
// lost and the extract failed with "No records were selected". //
//////////////////////////////////////////////////////////////////////////
processMetaData.withStep(1, new QFrontendStepMetaData()
.withName("input")
.withComponent(new QFrontendComponentMetaData()
.withType(QComponentType.EDIT_FORM))
@@ -0,0 +1,91 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2025. 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.qbits.webhooks.processes;
import java.util.List;
import com.kingsrook.qbits.webhooks.BaseTest;
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallback;
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
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 org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/*******************************************************************************
** Runs SendTestEventToWebhook the way a UI does: records are given only when
** the process starts (the init call); the continuation of the first screen
** carries no records.
*******************************************************************************/
class SendTestEventToWebhookProcessTest extends BaseTest
{
/*******************************************************************************
** The records chosen at init must still be there after the input screen.
*******************************************************************************/
@Test
void testRecordsFromInitSurviveTheInputScreen() throws QException
{
Integer webhookId = insert(newWebhook("Test receiver"));
///////////////////////////////////////////////////////////////////////
// init: records come in through the callback, as the UI API's init //
// passes recordIds; the run stops at the first frontend step //
///////////////////////////////////////////////////////////////////////
RunProcessInput initInput = new RunProcessInput();
initInput.setProcessName(SendTestEventToWebhookProcessMetaDataProducer.NAME);
initInput.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.BREAK);
initInput.setCallback(new QProcessCallback()
{
@Override
public QQueryFilter getQueryFilter()
{
return (new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.IN, List.of(webhookId))));
}
});
RunProcessOutput initOutput = new RunProcessAction().execute(initInput);
assertThat(initOutput.getException()).isEmpty();
assertThat(initOutput.getProcessState().getNextStepName()).contains("input");
//////////////////////////////////////////////////////////////////////
// continue after the input screen, with no callback: the extract //
// must still find the webhook chosen at init //
//////////////////////////////////////////////////////////////////////
RunProcessInput stepInput = new RunProcessInput();
stepInput.setProcessName(SendTestEventToWebhookProcessMetaDataProducer.NAME);
stepInput.setProcessUUID(initOutput.getProcessUUID());
stepInput.setStartAfterStep("input");
stepInput.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.BREAK);
stepInput.addValue("uponSuccessUpdateUnhealthyWebhooksToProbation", true);
RunProcessOutput stepOutput = new RunProcessAction().execute(stepInput);
assertThat(stepOutput.getException()).isEmpty();
assertThat(stepOutput.getProcessState().getNextStepName()).contains("review");
assertThat(stepOutput.getValues().get("recordCount")).isEqualTo(1);
}
}