Index: tests/test_schedule.py
===================================================================
--- tests/test_schedule.py	(revision 37ae3b7a7d6a55d792756e3a2d9dae3efbd2083c)
+++ tests/test_schedule.py	(revision d7a66adcde1b540a909fdf9593a32fcc0db09e1b)
@@ -1,110 +1,112 @@
 import pytest
+import json
 from flowtimer.Schedule import Schedule
 from flowtimer.Phase import Phase
+from flowtimer.RecurringPhaseSequence import RecurringPhaseSequence
+
 
 class TestSchedule:
-    
-    def test_schedule_initialization(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        assert schedule.phase_list == [phase1, phase2]
-        assert schedule.current_phase == phase1
+
+    @pytest.fixture
+    def setup_schedule(self):
+        #  Set up some real Phase and RecurringPhaseSequence objects for testing
+        phase1 = Phase("Phase 1", 300)
+        phase2 = Phase("Phase 2", 600)
+        sequence = RecurringPhaseSequence("Sequence 1", [phase1, phase2], 2)
+        blocks = [phase1, sequence]
+        schedule = Schedule("Test Schedule", blocks)
+        return schedule, phase1, phase2, sequence
+
+    def test_initialization(self, setup_schedule):
+        schedule, phase1, _, _ = setup_schedule
+        assert schedule.title == "Test Schedule"
+        assert schedule.blocks == [phase1, schedule.blocks[1]]
+        assert schedule.current_block == phase1
         assert schedule.state == "initial"
 
-    def test_schedule_start(self):
-        phase1 = Phase("Warm-up", 300)
-        schedule = Schedule([phase1])
+    def test_default_json_string(self):
+        default_json = Schedule.default_json_string()
+        assert isinstance(default_json, str)
+
+    def test_from_json(self):
+        json_string = Schedule.default_json_string()
+        schedule = Schedule.from_json(json_string)
+        assert schedule.title == "Default"
+        assert len(schedule.blocks) == 2
+        assert isinstance(schedule.blocks[0], Phase)
+        assert isinstance(schedule.blocks[1], RecurringPhaseSequence)
+
+    def test_to_json(self, setup_schedule):
+        schedule, _, _, _ = setup_schedule
+        json_string = schedule.to_json()
+        assert isinstance(json_string, str)
+        data = json.loads(json_string)
+        assert data['title'] == "Test Schedule"
+        assert len(data['blocks']) == 2
+
+    def test_start(self, setup_schedule):
+        schedule, phase1, _, _ = setup_schedule
         schedule.start()
-    
         assert schedule.state == "running"
-        assert schedule.current_phase.running() is True
-    
-    def test_schedule_pause(self):
-        phase1 = Phase("Warm-up", 300)
-        schedule = Schedule([phase1])
+        # assert phase1.ticks_left < phase1.initial_ticks  # Assuming the phase reduces ticks when started
+
+    def test_running(self, setup_schedule):
+        schedule, _, _, _ = setup_schedule
         schedule.start()
+        assert schedule.running() is True
         schedule.pause()
-    
-        assert schedule.state == "paused"
-        assert schedule.is_paused() is True
+        assert schedule.running() is False
 
-    def test_schedule_abort(self):
-        phase1 = Phase("Warm-up", 300)
-        schedule = Schedule([phase1])
-        schedule.start()
+    def test_paused(self, setup_schedule):
+        schedule, _, _, _ = setup_schedule
+        schedule.pause()
+        assert schedule.paused() is True
+
+    def test_abort(self, setup_schedule):
+        schedule, _, _, _ = setup_schedule
         schedule.abort()
-    
-        assert schedule.state == "finished"
-        assert schedule.current_phase.finished() is True
+        assert schedule.state == "aborted"
 
-    def test_schedule_finished(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        assert schedule.finished() is False
-    
-        phase1.start()
-        phase1.tick(300)
-        assert phase1.finished() is True
-        assert schedule.finished() is False
-    
+    def test_completed(self, setup_schedule):
+        schedule, phase1, _, sequence = setup_schedule
+        schedule.tick(phase1.initial_ticks)  # Complete phase1
+        schedule.tick(sequence.initial_ticks)  # Complete sequence
+        schedule.tick(phase1.initial_ticks)  # Complete phase1
+        schedule.tick(sequence.initial_ticks)  # Complete sequence
+        print(schedule.current_block)
+        assert schedule.completed() is True
+        assert schedule.state == "completed"
+
+    def test_advance_to_next_block(self, setup_schedule):
+        schedule, _, _, sequence = setup_schedule
+        schedule.advance_to_next_block()
+        assert schedule.current_block == schedule.blocks[1]
+
+    def test_skip(self, setup_schedule):
+        schedule, _, _, sequence = setup_schedule
         schedule.skip()
-        schedule.current_phase.tick(600)
-        assert schedule.finished() is True
+        assert schedule.current_block == schedule.blocks[1]  # Should skip to Phase 2 within the sequence
 
-    def test_schedule_skip(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        schedule.start()
-        schedule.skip()
-    
-        assert schedule.current_phase == phase2
+    def test_total_ticks_left(self, setup_schedule):
+        schedule, phase1, phase2, sequence = setup_schedule
+        expected_total_ticks = phase1.ticks_left + sequence.ticks_left
+        assert schedule.total_ticks_left() == expected_total_ticks
 
-    def test_schedule_skip_at_final_phase(self):
-        phase1 = Phase("Warm-up", 300)
-        schedule = Schedule([phase1])
-    
-        schedule.start()
-        schedule.skip()
-    
-        assert schedule.state == "finished"
+    def test_upcoming_blocks(self, setup_schedule):
+        schedule, _, _, sequence = setup_schedule
+        assert schedule.upcoming_blocks() == [sequence]
 
-    def test_schedule_tick(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        schedule.start()
-        schedule.tick(300)
-    
-        assert phase1.finished() is True
-        assert schedule.current_phase == phase2
-        assert schedule.state == "running"
+    def test_current_block_is_final(self, setup_schedule):
+        schedule, _, _, sequence = setup_schedule
+        assert schedule.current_block_is_final() is False
+        schedule.advance_to_next_block()
+        assert schedule.current_block_is_final() is True
 
-    def test_schedule_tick_to_completion(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        schedule.start()
-        schedule.tick(300)  # Should finish phase1 and move to phase2
-        schedule.tick(600)  # Should finish phase2 and complete the schedule
-    
-        assert phase2.finished() is True
-        assert schedule.finished() is True
+    def test_tick(self, setup_schedule):
+        schedule, phase1, _, _ = setup_schedule
+        initial_ticks = phase1.ticks_left
+        schedule.tick(100)
+        assert phase1.ticks_left == initial_ticks - 100
 
-    def test_schedule_current_phase_is_final(self):
-        phase1 = Phase("Warm-up", 300)
-        phase2 = Phase("Workout", 600)
-        schedule = Schedule([phase1, phase2])
-    
-        assert schedule.current_phase_is_final() is False
-    
-        schedule.skip()
-        assert schedule.current_phase_is_final() is True
-
+        schedule.tick(phase1.ticks_left)  # Finish phase1
+        assert schedule.current_block == schedule.blocks[1]  # Should advance to the next block
