"""Tests für layout.first_fit (BUG-04). Behauptung: Add-Item darf bestehende Items NICHT verschieben. - Leeres Layout → Add 2×2 hello → Position (0,0), kein Pack - Layout mit Lücke → Add 1×1 hello → landet in erster Lücke, andere bleiben - Layout voll → Add → None, kein anderes Item verändert """ import os, sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import unittest from layout import Item, first_fit, GRID_COLS, GRID_ROWS class TestFirstFit(unittest.TestCase): def test_first_fit_empty_grid(self): """Auf leerem Grid wird Item bei (0,0) platziert — kein Pack nötig.""" new_item = Item("new1", "hello", 0, 0, 1, 1) placed = first_fit(new_item, []) self.assertIsNotNone(placed) self.assertEqual((placed.x, placed.y), (0, 0)) def test_first_fit_does_not_move_existing(self): """Items mit Lücke: hello wird in Lücke gesetzt, andere bleiben.""" existing = [ Item("a", "clock", 0, 0, 2, 2), Item("b", "weather", 2, 0, 2, 2), Item("c", "system", 0, 2, 2, 2), Item("d", "spotify", 2, 2, 2, 1), ] before = {(it.id, it.x, it.y) for it in existing} new_item = Item("new", "hello", 0, 0, 1, 1) placed = first_fit(new_item, existing) self.assertIsNotNone(placed) after = {(it.id, it.x, it.y) for it in existing} self.assertEqual(before, after, f"EXISTING MOVED! before={before} after={after}") self.assertEqual((placed.x, placed.y), (2, 3)) def test_first_fit_full_grid_returns_none(self): """Wenn kein Platz: None zurück, keine Mutation.""" existing = [ Item("a", "x", 0, 0, 2, 2), Item("b", "y", 2, 0, 2, 2), Item("c", "z", 0, 2, 2, 2), Item("d", "w", 2, 2, 2, 2), ] before = {(it.id, it.x, it.y, it.w, it.h) for it in existing} new_item = Item("new", "hello", 0, 0, 1, 1) placed = first_fit(new_item, existing) self.assertIsNone(placed) after = {(it.id, it.x, it.y, it.w, it.h) for it in existing} self.assertEqual(before, after) if __name__ == "__main__": unittest.main(verbosity=2)