item.test.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { describe, it, expect, vi } from 'vitest';
  2. import { Item, BallItem, LineClearItem } from '../src/entities/Item.js';
  3. import { GRID_GAP, ITEM_SIZE_RATIO } from '../src/constants.js';
  4. describe('Item (base class)', () => {
  5. describe('constructor', () => {
  6. it('initializes with correct properties', () => {
  7. const item = new Item(3, 2, 'ball', 40);
  8. expect(item.gridX).toBe(3);
  9. expect(item.gridY).toBe(2);
  10. expect(item.type).toBe('ball');
  11. expect(item.size).toBe(40);
  12. expect(item.collected).toBe(false);
  13. });
  14. });
  15. describe('getRect()', () => {
  16. it('converts grid coordinates to pixel coordinates with reduced size', () => {
  17. const size = 40;
  18. const item = new Item(2, 3, 'ball', size);
  19. const rect = item.getRect();
  20. const itemSize = size * ITEM_SIZE_RATIO;
  21. const offset = (size - itemSize) / 2;
  22. expect(rect.x).toBe(2 * (size + GRID_GAP) + GRID_GAP + offset);
  23. expect(rect.y).toBe(3 * (size + GRID_GAP) + GRID_GAP + offset);
  24. expect(rect.width).toBe(itemSize);
  25. expect(rect.height).toBe(itemSize);
  26. });
  27. it('returns correct rect for origin (0,0)', () => {
  28. const size = 50;
  29. const item = new Item(0, 0, 'ball', size);
  30. const rect = item.getRect();
  31. const itemSize = size * ITEM_SIZE_RATIO;
  32. const offset = (size - itemSize) / 2;
  33. expect(rect.x).toBe(GRID_GAP + offset);
  34. expect(rect.y).toBe(GRID_GAP + offset);
  35. expect(rect.width).toBe(itemSize);
  36. expect(rect.height).toBe(itemSize);
  37. });
  38. });
  39. describe('shouldRemove()', () => {
  40. it('returns false by default', () => {
  41. const item = new Item(0, 0, 'ball', 40);
  42. expect(item.shouldRemove()).toBe(false);
  43. });
  44. });
  45. describe('moveDown()', () => {
  46. it('increments gridY by 1', () => {
  47. const item = new Item(3, 2, 'ball', 40);
  48. item.moveDown();
  49. expect(item.gridY).toBe(3);
  50. });
  51. });
  52. });
  53. describe('BallItem', () => {
  54. describe('constructor', () => {
  55. it('initializes with type "ball"', () => {
  56. const item = new BallItem(1, 2, 40);
  57. expect(item.type).toBe('ball');
  58. expect(item.gridX).toBe(1);
  59. expect(item.gridY).toBe(2);
  60. expect(item.collected).toBe(false);
  61. });
  62. });
  63. describe('onCollect()', () => {
  64. it('calls game.addPendingBall() and marks collected', () => {
  65. const game = { addPendingBall: vi.fn() };
  66. const item = new BallItem(0, 0, 40);
  67. item.onCollect(game);
  68. expect(game.addPendingBall).toHaveBeenCalledOnce();
  69. expect(item.collected).toBe(true);
  70. });
  71. });
  72. describe('shouldRemove()', () => {
  73. it('returns true (ball items are removed on collect)', () => {
  74. const item = new BallItem(0, 0, 40);
  75. expect(item.shouldRemove()).toBe(true);
  76. });
  77. });
  78. });
  79. describe('LineClearItem', () => {
  80. describe('constructor', () => {
  81. it('initializes with type "lineClear"', () => {
  82. const item = new LineClearItem(4, 5, 40, 'horizontal');
  83. expect(item.type).toBe('lineClear');
  84. expect(item.gridX).toBe(4);
  85. expect(item.gridY).toBe(5);
  86. expect(item.collected).toBe(false);
  87. expect(item.direction).toBe('horizontal');
  88. });
  89. });
  90. describe('onCollect()', () => {
  91. it('marks collected and calls clearRow for horizontal direction', () => {
  92. const game = { clearRow: vi.fn(), clearColumn: vi.fn() };
  93. const item = new LineClearItem(3, 7, 40, 'horizontal');
  94. item.onCollect(game);
  95. expect(item.collected).toBe(true);
  96. expect(game.clearRow).toHaveBeenCalledWith(7);
  97. expect(game.clearColumn).not.toHaveBeenCalled();
  98. });
  99. it('marks collected and calls clearColumn for vertical direction', () => {
  100. const game = { clearRow: vi.fn(), clearColumn: vi.fn() };
  101. const item = new LineClearItem(5, 2, 40, 'vertical');
  102. item.onCollect(game);
  103. expect(item.collected).toBe(true);
  104. expect(game.clearColumn).toHaveBeenCalledWith(5);
  105. expect(game.clearRow).not.toHaveBeenCalled();
  106. });
  107. it('triggers clear each time onCollect is called', () => {
  108. const game = { clearRow: vi.fn(), clearColumn: vi.fn() };
  109. const item = new LineClearItem(3, 2, 40, 'horizontal');
  110. item.onCollect(game);
  111. item.onCollect(game);
  112. expect(game.clearRow).toHaveBeenCalledTimes(2);
  113. });
  114. });
  115. describe('shouldRemove()', () => {
  116. it('returns false before collection', () => {
  117. const item = new LineClearItem(0, 0, 40, 'horizontal');
  118. expect(item.shouldRemove()).toBe(false);
  119. });
  120. it('returns false after collection (stays on board)', () => {
  121. const game = { clearRow: vi.fn(), clearColumn: vi.fn() };
  122. const item = new LineClearItem(0, 0, 40, 'horizontal');
  123. item.onCollect(game);
  124. expect(item.shouldRemove()).toBe(false);
  125. });
  126. });
  127. });