refactor(code-executor): migrate user scripts to single context argument

- replace (page, context, helpers) signature with async (context) => {}
- add ScriptContext interface exposing page, browser, env, getEnv,
  getCredential, getStepOutput, runSnippet, dumpDom, log/warn/error
- rename getEnvUrl to getEnv throughout service and docs
- fix step ordering: normalizeStepOrder and run step rows are now 1-based
- migrate existing DB rows (scenario_steps, scenario_run_steps) +1
- update all tests and stored snippet/step code in DB to new API
This commit is contained in:
2026-04-14 17:44:59 +03:00
parent 1a2e786ca8
commit 90be5a5490
10 changed files with 166 additions and 91 deletions
+10 -10
View File
@@ -1,6 +1,6 @@
/**
* Integration tests for ScenarioRunStepEntity.output column and the
* helpers.getStepOutput() API available inside exec step scripts.
* context.getStepOutput() API available inside exec step scripts.
*
* Strategy:
* - Seed a session row so the scheduler can create a browser context.
@@ -17,7 +17,7 @@ import { ScenarioService } from "../src/scenario/scenario.service";
import { ScenarioSchedulerService } from "../src/scenario/scenario-scheduler.service";
import { EnvironmentEntity } from "../src/environment/environment.entity";
describe("ScenarioRunStepEntity.output + helpers.getStepOutput", () => {
describe("ScenarioRunStepEntity.output + context.getStepOutput", () => {
let app: INestApplication;
let dataSource: DataSource;
let scenarioService: ScenarioService;
@@ -135,15 +135,15 @@ describe("ScenarioRunStepEntity.output + helpers.getStepOutput", () => {
});
});
// ── helpers.getStepOutput ──────────────────────────────────────────────────
// ── context.getStepOutput ──────────────────────────────────────────────────
describe("helpers.getStepOutput()", () => {
describe("context.getStepOutput()", () => {
it("returns output of a previous step by absolute order", async () => {
await seedSession();
const scId = await createScenario("getStepOutput-absolute");
await createStep(scId, 0, "return 99;");
// Step 1 reads step 0's output via absolute index 0
await createStep(scId, 1, "return await helpers.getStepOutput(0);");
// Step 1 reads step 1's output via absolute index 1 (1-based)
await createStep(scId, 1, "return await context.getStepOutput(1);");
const runId = await runScenario(scId);
const rows = await dataSource.query(
@@ -159,7 +159,7 @@ describe("ScenarioRunStepEntity.output + helpers.getStepOutput", () => {
const scId = await createScenario("getStepOutput-relative");
await createStep(scId, 0, 'return "step-zero";');
// Step 1 uses relative index -1 to reference step 0
await createStep(scId, 1, "return await helpers.getStepOutput(-1);");
await createStep(scId, 1, "return await context.getStepOutput(-1);");
const runId = await runScenario(scId);
const rows = await dataSource.query(
@@ -173,7 +173,7 @@ describe("ScenarioRunStepEntity.output + helpers.getStepOutput", () => {
await seedSession();
const scId = await createScenario("getStepOutput-missing");
// Step 0 tries to read step order 99 which does not exist
await createStep(scId, 0, "return await helpers.getStepOutput(99);");
await createStep(scId, 0, "return await context.getStepOutput(99);");
const runId = await runScenario(scId);
const row = await dataSource.query(
@@ -190,12 +190,12 @@ describe("ScenarioRunStepEntity.output + helpers.getStepOutput", () => {
await createStep(
scId,
1,
"const prev = await helpers.getStepOutput(-1); return [...prev, 3];",
"const prev = await context.getStepOutput(-1); return [...prev, 3];",
);
await createStep(
scId,
2,
"const prev = await helpers.getStepOutput(-1); return [...prev, 4];",
"const prev = await context.getStepOutput(-1); return [...prev, 4];",
);
const runId = await runScenario(scId);