| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- import { describe, it, expect } from 'vitest';
- import * as fc from 'fast-check';
- import { Block } from '../src/entities/Block.js';
- import { GRID_GAP } from '../src/constants.js';
- describe('Block', () => {
- describe('constructor', () => {
- it('initializes with correct properties', () => {
- const block = new Block(3, 2, 5, 40);
- expect(block.gridX).toBe(3);
- expect(block.gridY).toBe(2);
- expect(block.count).toBe(5);
- expect(block.size).toBe(40);
- expect(block.destroyed).toBe(false);
- });
- });
- describe('hit()', () => {
- it('decrements count by 1', () => {
- const block = new Block(0, 0, 5, 40);
- block.hit();
- expect(block.count).toBe(4);
- });
- it('returns false when count > 0 after hit', () => {
- const block = new Block(0, 0, 3, 40);
- expect(block.hit()).toBe(false);
- });
- it('marks destroyed and returns true when count reaches 0', () => {
- const block = new Block(0, 0, 1, 40);
- expect(block.hit()).toBe(true);
- expect(block.destroyed).toBe(true);
- expect(block.count).toBe(0);
- });
- it('marks destroyed when count goes below 0', () => {
- const block = new Block(0, 0, 0, 40);
- expect(block.hit()).toBe(true);
- expect(block.destroyed).toBe(true);
- expect(block.count).toBe(-1);
- });
- });
- describe('getRect()', () => {
- it('converts grid coordinates to pixel coordinates', () => {
- const size = 40;
- const block = new Block(2, 3, 5, size);
- const rect = block.getRect();
- expect(rect.x).toBe(2 * (size + GRID_GAP) + GRID_GAP);
- expect(rect.y).toBe(3 * (size + GRID_GAP) + GRID_GAP);
- expect(rect.width).toBe(size);
- expect(rect.height).toBe(size);
- });
- it('returns correct rect for origin block (0,0)', () => {
- const size = 50;
- const block = new Block(0, 0, 1, size);
- const rect = block.getRect();
- expect(rect.x).toBe(GRID_GAP);
- expect(rect.y).toBe(GRID_GAP);
- expect(rect.width).toBe(size);
- expect(rect.height).toBe(size);
- });
- });
- describe('getColor()', () => {
- it('returns a valid hex color string', () => {
- const block = new Block(0, 0, 10, 40);
- const color = block.getColor();
- expect(color).toMatch(/^#[0-9a-f]{6}$/);
- });
- it('returns different colors for different counts', () => {
- const block1 = new Block(0, 0, 1, 40);
- const block2 = new Block(0, 0, 50, 40);
- expect(block1.getColor()).not.toBe(block2.getColor());
- });
- });
- describe('isDestroyed()', () => {
- it('returns false when count > 0', () => {
- const block = new Block(0, 0, 5, 40);
- expect(block.isDestroyed()).toBe(false);
- });
- it('returns true when count is 0', () => {
- const block = new Block(0, 0, 0, 40);
- expect(block.isDestroyed()).toBe(true);
- });
- it('returns true when count is negative', () => {
- const block = new Block(0, 0, -1, 40);
- expect(block.isDestroyed()).toBe(true);
- });
- });
- describe('moveDown()', () => {
- it('increments gridY by 1', () => {
- const block = new Block(3, 2, 5, 40);
- block.moveDown();
- expect(block.gridY).toBe(3);
- });
- it('can be called multiple times', () => {
- const block = new Block(0, 0, 5, 40);
- block.moveDown();
- block.moveDown();
- block.moveDown();
- expect(block.gridY).toBe(3);
- });
- });
- // Feature: ball-block-breaker, Property 7: 碰撞方块数字减1
- // **Validates: Requirements 4.1**
- describe('Property 7: 碰撞方块数字减1', () => {
- it('hit() decrements count by exactly 1 for any block with count > 0', () => {
- fc.assert(
- fc.property(
- fc.integer({ min: 1, max: 10000 }),
- fc.integer({ min: 0, max: 6 }),
- fc.integer({ min: 0, max: 20 }),
- fc.constantFrom(30, 40, 50),
- (count, gridX, gridY, size) => {
- const block = new Block(gridX, gridY, count, size);
- const originalCount = block.count;
- block.hit();
- expect(block.count).toBe(originalCount - 1);
- }
- ),
- { numRuns: 100 }
- );
- });
- });
- });
|