Files
OpenNoodl/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-012-blockly-integration/TASK-012C-noodl-blocks-and-testing.md
2026-01-12 13:23:12 +01:00

11 KiB
Raw Blame History

TASK-012C: Noodl Blocks and End-to-End Testing

Status: Not Started
Depends On: TASK-012B (Bug Fixes - Completed)
Estimated Duration: 8-12 hours
Priority: High

Overview

Complete the Logic Builder by adding Noodl-specific blocks and perform end-to-end testing to verify data flow between the Logic Builder node and the standard Noodl canvas.

Current State

What's Working

  • Blockly workspace renders in tabs
  • Tab system functional (open/close/switch)
  • Basic Blockly categories (Logic, Math, Text)
  • Property panel "Edit Blocks" button
  • Workspace auto-save
  • Dynamic port detection framework
  • JavaScript code generation

⚠️ Known Issues

  • Drag-and-drop has 1000ms timeout (see DRAG-DROP-ISSUE.md)
  • Only basic Blockly blocks available (no Noodl-specific blocks)
  • No Noodl API integration blocks yet
  • Untested: Actual data flow from inputs → Logic Builder → outputs

📦 Existing Infrastructure

Files:

  • NoodlBlocks.ts - Block definitions (placeholders exist)
  • NoodlGenerators.ts - Code generators (placeholders exist)
  • IODetector.ts - Dynamic port detection
  • logic-builder.js - Runtime node
  • BlocklyEditorGlobals.ts - Runtime bridge

Goals

  1. Audit Standard Blockly Blocks - Determine which to keep/remove
  2. Implement Noodl API Blocks - Inputs, Outputs, Variables, Objects, Arrays
  3. Test End-to-End Data Flow - Verify Logic Builder works as a functional node
  4. Document Patterns - Create guide for adding future blocks

Phase 1: Standard Blockly Block Audit

Objective

Review Blockly's default blocks and decide which are valuable for Noodl users vs adding clutter.

Current Default Blocks

Logic Category:

  • controls_if - If/else conditionals
  • logic_compare - Comparison operators (==, !=, <, >)
  • logic_operation - Boolean operators (AND, OR)
  • logic_negate - NOT operator
  • logic_boolean - True/False values

Math Category:

  • math_number - Number input
  • math_arithmetic - Basic operations (+, -, ×, ÷)
  • math_single - Functions (sqrt, abs, etc.)

Text Category:

  • text - String input
  • text_join - Concatenate strings
  • text_length - String length

Decision Criteria

For each category, determine:

  • Keep: Fundamental programming concepts that align with Noodl
  • Remove: Overly technical or redundant with Noodl nodes
  • Add Later: Useful but not MVP (e.g., loops, lists)

Recommendations

Logic - KEEP ALL

  • Essential for conditional logic
  • Aligns with Noodl's event-driven model

Math - KEEP BASIC

  • Keep: number, arithmetic
  • Consider: single (advanced math functions)
  • Reason: Basic math is useful; advanced math might be better as Data nodes

Text - KEEP ALL

  • String manipulation is common
  • Lightweight and useful

NOT INCLUDED YET (Consider for future):

  • Loops (for, while) - Complex for visual editor
  • Lists/Arrays - Would need Noodl-specific implementation
  • Functions - Covered by components in Noodl
  • Variables - Covered by Noodl Variables system

Action Items

  • Create custom toolbox config with curated blocks
  • Test each block generates valid JavaScript
  • Document reasoning for inclusions/exclusions

Phase 2: Noodl API Blocks Implementation

2.1 Input Blocks

Purpose: Read values from node inputs

Blocks Needed:

  1. Get Input

    • Dropdown selector for input names
    • Returns current input value
    • Code: Noodl.Inputs['inputName']
  2. Define Input

    • Text field for input name
    • Dropdown for type (String, Number, Boolean, Signal)
    • Creates dynamic port on node
    • Code: Registers input via IODetector

Implementation:

// In NoodlBlocks.ts
Blockly.Blocks['noodl_get_input'] = {
  init: function () {
    this.appendDummyInput().appendField('get input').appendField(new Blockly.FieldTextInput('inputName'), 'INPUT_NAME');
    this.setOutput(true, null);
    this.setColour(290);
    this.setTooltip('Get value from node input');
  }
};

// In NoodlGenerators.ts
javascriptGenerator.forBlock['noodl_get_input'] = function (block) {
  const inputName = block.getFieldValue('INPUT_NAME');
  return [`Noodl.Inputs['${inputName}']`, Order.MEMBER];
};

2.2 Output Blocks

Purpose: Send values to node outputs

Blocks Needed:

  1. Set Output

    • Dropdown/text for output name
    • Value input socket
    • Code: Noodl.Outputs['outputName'] = value
  2. Define Output

    • Text field for output name
    • Dropdown for type
    • Creates dynamic port on node
    • Code: Registers output via IODetector
  3. Send Signal

    • Dropdown for signal output name
    • Code: Noodl.Outputs['signalName'] = true

2.3 Variable Blocks

Purpose: Access Noodl Variables

Blocks Needed:

  1. Get Variable

    • Dropdown for variable name (from project)
    • Code: Noodl.Variables['varName']
  2. Set Variable

    • Dropdown for variable name
    • Value input
    • Code: Noodl.Variables['varName'] = value

2.4 Object Blocks

Purpose: Work with Noodl Objects

Blocks Needed:

  1. Get Object

    • Text input for object ID
    • Code: Noodl.Objects['objectId']
  2. Get Object Property

    • Object input socket
    • Property name field
    • Code: object['propertyName']
  3. Set Object Property

    • Object input socket
    • Property name field
    • Value input socket
    • Code: object['propertyName'] = value

2.5 Array Blocks

Purpose: Work with Noodl Arrays

Blocks Needed:

  1. Get Array

    • Text input for array name
    • Code: Noodl.Arrays['arrayName']
  2. Array Length

    • Array input socket
    • Code: array.length
  3. Get Array Item

    • Array input socket
    • Index input
    • Code: array[index]
  4. Add to Array

    • Array input socket
    • Value input
    • Code: array.push(value)

Implementation Priority

MVP (Must Have):

  1. Get Input / Set Output (core functionality)
  2. Variables (get/set)
  3. Send Signal

Phase 2 (Important): 4. Objects (get/get property/set property) 5. Define Input/Define Output (dynamic ports)

Phase 3 (Nice to Have): 6. Arrays (full CRUD operations)


Phase 3: IODetector Enhancement

Current State

IODetector.ts exists but needs verification:

  • Scans workspace JSON for Noodl block usage
  • Detects input/output references
  • Reports required ports to editor

Tasks

  • Review IODetector logic
  • Add support for "Define Input/Output" blocks
  • Handle variable/object/array references
  • Test with various block combinations

Expected Detection

// Workspace contains:
// - Get Input "userName"
// - Set Output "greeting"
// - Send Signal "done"

// IODetector should return:
{
  inputs: [
    { name: 'userName', type: 'string' }
  ],
  outputs: [
    { name: 'greeting', type: 'string' },
    { name: 'done', type: 'signal' }
  ]
}

Phase 4: End-to-End Testing

4.1 Basic Flow Test

Setup:

  1. Add Logic Builder node to canvas
  2. Open Logic Builder editor
  3. Create simple logic:
    • Get Input "name"
    • Concatenate with "Hello, "
    • Set Output "greeting"

Expected:

  • Input port "name" appears on node
  • Output port "greeting" appears on node
  • Text input node → Logic Builder → Text node shows correct value

4.2 Signal Test

Setup:

  1. Logic Builder with "Send Signal 'done'" block

Expected:

  • Signal output "done" appears
  • Connecting to another node triggers it properly

4.3 Variable Test

Setup:

  1. Create Variable "counter"
  2. Logic Builder:
    • Get Variable "counter"
    • Add 1
    • Set Variable "counter"
    • Set Output "currentCount"

Expected:

  • Variable updates globally
  • Output shows incremented value

4.4 Object Test

Setup:

  1. Create Object with property "score"
  2. Logic Builder:
    • Get Object "player"
    • Get Property "score"
    • Add 10
    • Set Property "score"

Expected:

  • Object property updates
  • Other nodes reading same object see change

Test Matrix

Test Inputs Logic Outputs Status
Pass-through value Get Input → Set Output value
Math a, b a + b sum
Conditional x if x > 10 then "high" else "low" result
Signal - Send Signal done signal
Variable - Get/Set Variable -
Object objId Get Object Property value

Phase 5: Documentation

5.1 User Guide

Create: LOGIC-BUILDER-USER-GUIDE.md

Contents:

  • What is Logic Builder?
  • When to use vs standard nodes
  • How to add inputs/outputs
  • Available blocks reference
  • Common patterns/examples

5.2 Developer Guide

Create: LOGIC-BUILDER-DEV-GUIDE.md

Contents:

  • Architecture overview
  • How to add new blocks
  • Code generation patterns
  • IODetector how-to
  • Troubleshooting guide

5.3 Known Limitations

Document in README:

  • Drag-and-drop timeout (1000ms)
  • No async/await support yet
  • No loop constructs yet
  • Data nodes not integrated

File Changes Required

New Files

  • dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-012-blockly-integration/LOGIC-BUILDER-USER-GUIDE.md
  • dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-012-blockly-integration/LOGIC-BUILDER-DEV-GUIDE.md

Modified Files

  • NoodlBlocks.ts - Add all Noodl API blocks
  • NoodlGenerators.ts - Add code generators for Noodl blocks
  • BlocklyWorkspace.tsx - Update toolbox configuration
  • IODetector.ts - Enhance detection logic
  • logic-builder.js - Verify runtime API exposure

Success Criteria

  • Standard Blockly blocks audited and documented
  • Noodl Input/Output blocks implemented
  • Noodl Variable blocks implemented
  • Noodl Object blocks implemented (basic)
  • Noodl Array blocks implemented (basic)
  • IODetector correctly identifies all port requirements
  • End-to-end tests pass (inputs → logic → outputs)
  • User guide written
  • Developer guide written
  • Examples created and tested

Future Enhancements (Not in This Task)

  • Data node integration (REST API, SQL, etc.)
  • Async/await support
  • Loop constructs
  • Custom block creation UI
  • Block library sharing
  • Visual debugging/step-through
  • Performance profiling
  • Fix drag-and-drop 1000ms timeout

  • TASK-012A - Foundation (Complete)
  • TASK-012B - Bug Fixes (Complete)
  • TASK-012C - This task
  • TASK-012D - Polish & Advanced Features (Future)

Notes

  • Keep blocks simple and aligned with Noodl concepts
  • Prioritize common use cases over exhaustive coverage
  • Document limitations clearly
  • Consider future extensibility in design