Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,34 @@ describe("WorkflowEditorComponent", () => {

expect(getStroke(mockScanPredicate.operatorID)).toBe("red");
});

it("uses the Validation passed in instead of recomputing it", () => {
// Let the validation chain settle from the operator-add so the spy
// below is created after those calls and starts with a clean slate.
workflowActionService.addOperator(mockScanPredicate, mockPoint);
fixture.detectChanges();

const validateSpy = vi.spyOn(validationWorkflowService, "validateOperator");

// Call the helper directly with a Validation argument, mirroring what
// the validation-stream subscriber does at runtime
// (handleOperatorValidation passes value.validation through).
(component as any).applyOperatorBorder(mockScanPredicate.operatorID, { isValid: true });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: this proves the recompute is skipped, but not that the passed-in value is used. Passing { isValid: false } and asserting the operator goes red would cover that too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in cda9952


expect(validateSpy).not.toHaveBeenCalled();
});

it("honors the passed-in Validation result (paints red when it is invalid)", () => {
// Proves the passed-in value actually drives the border, not just that
// the recompute is skipped: an invalid result must paint red.
vi.spyOn(workflowStatusService, "getCurrentStatus").mockReturnValue({});
workflowActionService.addOperator(mockScanPredicate, mockPoint);
fixture.detectChanges();

(component as any).applyOperatorBorder(mockScanPredicate.operatorID, { isValid: false, messages: {} });

expect(getStroke(mockScanPredicate.operatorID)).toBe("red");
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { DragDropService } from "../../service/drag-drop/drag-drop.service";
import { DynamicSchemaService } from "../../service/dynamic-schema/dynamic-schema.service";
import { ExecuteWorkflowService } from "../../service/execute-workflow/execute-workflow.service";
import { fromJointPaperEvent, JointUIService, linkPathStrokeColor } from "../../service/joint-ui/joint-ui.service";
import { ValidationWorkflowService } from "../../service/validation/validation-workflow.service";
import { Validation, ValidationWorkflowService } from "../../service/validation/validation-workflow.service";
import { WorkflowActionService } from "../../service/workflow-graph/model/workflow-action.service";
import { WorkflowStatusService } from "../../service/workflow-status/workflow-status.service";
import { ExecutionState, OperatorState } from "../../types/execute-workflow.interface";
Expand Down Expand Up @@ -397,10 +397,14 @@ export class WorkflowEditorComponent implements OnInit, AfterViewInit, OnDestroy
* Centralizing this here avoids the race where the validation pass
* overwrites a state-derived stroke (or vice versa) for an operator that
* is both invalid and has a cached execution status.
*
* Callers that already have a Validation result (the validation stream
* subscriber) may pass it in to avoid recomputing it; callers without one
* (the operator-add stream subscriber) let the helper fetch it lazily.
*/
private applyOperatorBorder(operatorID: string): void {
const validation = this.validationWorkflowService.validateOperator(operatorID);
if (!validation.isValid) {
private applyOperatorBorder(operatorID: string, validation?: Validation): void {
const resolved = validation ?? this.validationWorkflowService.validateOperator(operatorID);
if (!resolved.isValid) {
this.jointUIService.changeOperatorColor(this.paper, operatorID, false);
return;
}
Comment thread
Yicong-Huang marked this conversation as resolved.
Expand Down Expand Up @@ -1025,7 +1029,7 @@ export class WorkflowEditorComponent implements OnInit, AfterViewInit, OnDestroy
this.validationWorkflowService
.getOperatorValidationStream()
.pipe(untilDestroyed(this))
.subscribe(value => this.applyOperatorBorder(value.operatorID));
.subscribe(value => this.applyOperatorBorder(value.operatorID, value.validation));
}

/**
Expand Down
Loading