Step run events were previously visible only on the run tab. Operators who triggered a run there and then switched to the graph tab saw a static graph — the canvas had no idea something was executing. Wire the run events through the FlowEditorController so all three tabs share the same status snapshot: - New StepRunStatus enum on the controller (idle / running / done / failed / awaiting). - controller.stepStatuses exposes the live map. - controller.updateStepStatus is called from the run tab's event handler — one source of truth, both views read it. - FlowCanvas drops its own stepStatuses parameter and pulls from the controller instead, so the canvas now shows the running pulse + done check + error cross + pause icon in each step's header live, in lockstep with the step list on the run tab. When a fresh run starts (controller.running = true) the status map is cleared so stale events from a previous run don't paint the new one. Signed-off-by: flemming-it <sf@flemming.it>
93 lines
2.6 KiB
Dart
93 lines
2.6 KiB
Dart
// Behaviour tests for FlowEditorController — the bridge
|
|
// between the YAML buffer + the graph + the layout sidecar.
|
|
// The model tests cover parsing correctness; these cover
|
|
// that the controller wires text -> graph reparsing,
|
|
// graph -> YAML emission, selection bookkeeping, and
|
|
// dirty/saved transitions correctly.
|
|
|
|
import 'package:fai_studio_flow_editor/src/editor_controller.dart';
|
|
import 'package:fai_studio_flow_editor/src/model/flow_graph.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
group('FlowEditorController', () {
|
|
test('openFlow seeds the graph + clears the dirty flag', () {
|
|
final c = FlowEditorController();
|
|
addTearDown(c.dispose);
|
|
c.openFlow('hello', '''
|
|
name: hello
|
|
inputs:
|
|
name: text
|
|
steps:
|
|
- id: greet
|
|
use: debug.echo@^0
|
|
with:
|
|
message: \$inputs.name
|
|
outputs:
|
|
greeting: \$greet.echoed
|
|
''');
|
|
expect(c.activeName, 'hello');
|
|
expect(c.graph.steps, hasLength(1));
|
|
expect(c.graph.steps.single.id, 'greet');
|
|
expect(c.isDirty, isFalse);
|
|
});
|
|
|
|
test('graph edit re-emits YAML into the text buffer', () {
|
|
final c = FlowEditorController();
|
|
addTearDown(c.dispose);
|
|
c.openFlow('demo', '''
|
|
name: demo
|
|
steps:
|
|
- id: a
|
|
use: debug.echo@^0
|
|
outputs: {}
|
|
''');
|
|
final initialText = c.codeController.fullText;
|
|
c.applyGraphEdit(
|
|
c.graph.withStepAdded(const FlowStep(id: 'b', use: 'debug.echo@^0')),
|
|
);
|
|
expect(c.codeController.fullText, isNot(initialText));
|
|
expect(c.codeController.fullText, contains('id: b'));
|
|
expect(c.graph.steps, hasLength(2));
|
|
});
|
|
|
|
test('graph edit marks the buffer dirty against the baseline', () {
|
|
final c = FlowEditorController();
|
|
addTearDown(c.dispose);
|
|
c.openFlow('demo', '''
|
|
steps:
|
|
- id: a
|
|
use: debug.echo@^0
|
|
outputs: {}
|
|
''');
|
|
expect(c.isDirty, isFalse);
|
|
c.applyGraphEdit(
|
|
c.graph.withStepAdded(const FlowStep(id: 'b', use: 'debug.echo@^0')),
|
|
);
|
|
expect(c.isDirty, isTrue);
|
|
c.markSaved();
|
|
expect(c.isDirty, isFalse);
|
|
});
|
|
|
|
test('selectStep notifies listeners only on change', () {
|
|
final c = FlowEditorController();
|
|
addTearDown(c.dispose);
|
|
c.openFlow('demo', '''
|
|
steps:
|
|
- id: only
|
|
use: debug.echo@^0
|
|
outputs: {}
|
|
''');
|
|
var calls = 0;
|
|
c.addListener(() => calls++);
|
|
c.selectStep('only');
|
|
final after = calls;
|
|
// Selecting the same thing again must NOT bump the
|
|
// listener count — the controller short-circuits.
|
|
c.selectStep('only');
|
|
expect(calls, after);
|
|
c.selectStep(null);
|
|
expect(calls, after + 1);
|
|
});
|
|
});
|
|
}
|