sprout-garden-phase-3-test
Test: Sprout Garden Phase 3
Following [[pattern-looking-glass-development]] - the tests ARE the documentation.
Subject
Phase 3 plot types: gates, lap-counter, exit-gate, merge, teleport (conditionals and loops)
config
path: null
plots_dir: /Users/graemefawcett/working/ben.fawcett.family/activities/sprout-garden/src/plots/typesSpec
Test: Gate Blocks Non-Matching Sprouts
describe('Gate Plot', () => {
it('starGate passes star-shaped sprouts', () => {
const gate = createGate({ shape: 'star' });
const sprout = { shape: 'star', color: 'red' };
expect(gate.canPass(sprout)).toBe(true);
});
it('starGate blocks non-star sprouts', () => {
const gate = createGate({ shape: 'star' });
const sprout = { shape: 'circle', color: 'red' };
expect(gate.canPass(sprout)).toBe(false);
});
it('colorGate checks color property', () => {
const gate = createGate({ color: 'blue' });
expect(gate.canPass({ shape: 'circle', color: 'blue' })).toBe(true);
expect(gate.canPass({ shape: 'circle', color: 'red' })).toBe(false);
});
it('gate grow() returns null when blocked', () => {
const gate = createGate({ shape: 'star' });
const sprout = { shape: 'circle', color: 'red' };
expect(gate.grow(sprout)).toBeNull();
});
});Test: Lap Counter Increments
describe('Lap Counter Plot', () => {
it('increments laps property', () => {
const counter = lapCounter;
const sprout = { shape: 'star', color: 'yellow', laps: 0 };
const result = counter.grow(sprout);
expect(result.laps).toBe(1);
});
it('creates laps property if missing', () => {
const counter = lapCounter;
const sprout = { shape: 'star', color: 'yellow' };
const result = counter.grow(sprout);
expect(result.laps).toBe(1);
});
it('preserves other sprout properties', () => {
const counter = lapCounter;
const sprout = { shape: 'star', color: 'yellow', laps: 3 };
const result = counter.grow(sprout);
expect(result.shape).toBe('star');
expect(result.color).toBe('yellow');
expect(result.laps).toBe(4);
});
it('has pass-through fruits', () => {
expect(lapCounter.fruits).toContain('pass-through');
});
});Test: Exit Gate Conditional
describe('Exit Gate Plot', () => {
it('blocks when laps < threshold', () => {
const gate = createExitGate({ laps: 5 });
const sprout = { shape: 'star', color: 'yellow', laps: 3 };
expect(gate.shouldExit(sprout)).toBe(false);
});
it('allows exit when laps >= threshold', () => {
const gate = createExitGate({ laps: 5 });
const sprout = { shape: 'star', color: 'yellow', laps: 5 };
expect(gate.shouldExit(sprout)).toBe(true);
});
it('has conditional fruits (exit vs loop)', () => {
const gate = createExitGate({ laps: 5 });
// When condition met: exit direction
// When not met: loop back direction
expect(gate.fruits).toContain('conditional');
});
});Test: Merge Accepts Multiple Inputs
describe('Merge Plot', () => {
it('accepts from all 4 directions', () => {
expect(merge.seeds).toContain('left');
expect(merge.seeds).toContain('right');
expect(merge.seeds).toContain('up');
expect(merge.seeds).toContain('down');
});
it('outputs to single direction', () => {
// Merge combines paths, outputs one way
expect(merge.fruits.length).toBe(1);
});
it('passes sprout through unchanged', () => {
const sprout = { shape: 'star', color: 'yellow', laps: 2 };
expect(merge.grow(sprout)).toEqual(sprout);
});
});Test: Teleport Jumps Position
describe('Teleport Plot', () => {
it('has target address as fruit', () => {
const teleport = createTeleport('A5');
// Teleport's fruit is a position, not a direction
expect(teleport.fruits).toContain('A5');
});
it('passes sprout through unchanged', () => {
const teleport = createTeleport('A5');
const sprout = { shape: 'star', color: 'yellow' };
expect(teleport.grow(sprout)).toEqual(sprout);
});
});Test: For-Loop Pattern
describe('For-Loop Pattern', () => {
it('sprout completes N laps before exit', () => {
const sim = new Simulation(raceTrackGarden);
const result = sim.run();
const finishedSprout = result.sprouts.find(s => s.status === 'arrived');
expect(finishedSprout.laps).toBe(5);
});
it('detects infinite loops', () => {
const sim = new Simulation(infiniteLoopGarden);
const result = sim.run(100); // Max ticks
const loopingSprout = result.sprouts.find(s => s.status === 'looping');
expect(loopingSprout).toBeDefined();
});
});Results
{
"summary": "0/5 tests passing",
"phase": "Phase 3: Gates & Loops",
"status": "not yet implemented",
"tests": [
{
"test": "gate.js exists",
"status": "fail",
"details": "not yet implemented"
},
{
"test": "lap-counter.js exists",
"status": "fail",
"details": "not yet implemented"
},
{
"test": "exit-gate.js exists",
"status": "fail",
"details": "not yet implemented"
},
{
"test": "merge.js exists",
"status": "fail",
"details": "not yet implemented"
},
{
"test": "teleport.js exists",
"status": "fail",
"details": "not yet implemented"
}
]
}Provenance
Fences
test-gate-blocks
- Status: Spec only (Phase 3 not implemented)
- By: Claude (2025-11-29)
- Note: Gate conditional logic
test-lap-counter
- Status: Spec only
- By: Claude (2025-11-29)
- Note: Counter increment behavior
test-exit-gate
- Status: Spec only
- By: Claude (2025-11-29)
- Note: Loop exit condition
test-merge
- Status: Spec only
- By: Claude (2025-11-29)
- Note: Path combining
test-teleport
- Status: Spec only
- By: Claude (2025-11-29)
- Note: Non-adjacent position jumping
test-for-loop-pattern
- Status: Spec only
- By: Claude (2025-11-29)
- Note: Integration test for race track
sprout-garden-phase-3-results
- Status: Verified (checks for implementation)
- By: Claude (2025-11-29)
- Note: Reports Phase 3 implementation status
Slots
North
slots:
- sprout-garden-phase-3South
slots: []East
slots: []West
slots:
- pattern-looking-glass-development
β northsprout-garden-phase-3