| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import 'package:flutter_test/flutter_test.dart';
- import 'package:flame/components.dart';
- import 'package:zentap/game/components/bubble.dart';
- import 'package:zentap/game/components/bubble_spawner.dart';
- import 'package:zentap/utils/tilt_detector.dart';
- void main() {
- group('Bubble Rules Tests', () {
- group('Rule 1: Screen Capacity Calculation', () {
- test('should calculate max bubbles for different screen sizes', () {
- // Test small screen (phone) - 360x640
- final phoneScreen = Vector2(360, 640);
- final phoneBubbles = BubbleSpawner.calculateMaxBubblesForScreenSize(phoneScreen);
- expect(phoneBubbles, greaterThan(0));
- expect(phoneBubbles, lessThanOrEqualTo(15)); // Within practical limits
-
- // Test large screen (tablet) - 768x1024
- final tabletScreen = Vector2(768, 1024);
- final tabletBubbles = BubbleSpawner.calculateMaxBubblesForScreenSize(tabletScreen);
- expect(tabletBubbles, greaterThan(phoneBubbles)); // Should be more than phone
- expect(tabletBubbles, lessThanOrEqualTo(15)); // Capped at 15
-
- // Test edge cases
- final tinyScreen = Vector2(100, 100);
- final tinyBubbles = BubbleSpawner.calculateMaxBubblesForScreenSize(tinyScreen);
- expect(tinyBubbles, equals(4)); // Minimum fallback
-
- // Test that phone screen gives reasonable number
- expect(phoneBubbles, greaterThanOrEqualTo(4));
- });
-
- test('should have practical limits between 4-15 bubbles', () {
- // Test various screen sizes
- final testSizes = [
- Vector2(360, 640), // Phone
- Vector2(768, 1024), // Tablet
- Vector2(1920, 1080), // Large screen
- Vector2(100, 100), // Tiny screen
- ];
-
- for (final size in testSizes) {
- final maxBubbles = BubbleSpawner.calculateMaxBubblesForScreenSize(size);
- expect(maxBubbles, greaterThanOrEqualTo(4));
- expect(maxBubbles, lessThanOrEqualTo(15));
- }
- });
-
- test('should calculate consistent results for same screen size', () {
- final screenSize = Vector2(480, 800);
-
- final result1 = BubbleSpawner.calculateMaxBubblesForScreenSize(screenSize);
- final result2 = BubbleSpawner.calculateMaxBubblesForScreenSize(screenSize);
-
- expect(result1, equals(result2));
- });
- });
-
- group('Rule 2: Triple Collision Auto-Pop', () {
- test('should track collision count correctly', () {
- final bubble = Bubble(position: Vector2(100, 100));
-
- // Initially no collisions
- expect(bubble.collisionCount, equals(0));
-
- // Note: Actual collision testing would require proper game setup
- // with collision detection system running
- });
-
- test('should reset collision count after grace period', () {
- final bubble = Bubble(position: Vector2(100, 100));
-
- // This test would verify that collision count resets
- // after Bubble.collisionGracePeriod (2.0 seconds)
- expect(bubble.collisionCount, equals(0));
- });
-
- test('should auto-pop after 3 collisions', () {
- final bubble = Bubble(position: Vector2(100, 100));
-
- // This test would simulate 3 collisions and verify
- // that the bubble automatically pops
- expect(Bubble.maxCollisions, equals(3));
- });
- });
-
- group('Rule 3: Single Bubble Per Shake', () {
- test('should debounce shake events', () {
- final detector = TiltDetector();
-
- expect(detector.isShakeDebounced, isFalse);
-
- // After a shake event, should be debounced for 500ms
- // Note: This would require simulating shake events
- });
-
- test('should prevent multiple shake events within debounce period', () {
- final detector = TiltDetector();
-
- // Test that rapid shake events are filtered out
- // Only one should be processed per 500ms window
- expect(detector.timeSinceLastShake, greaterThanOrEqualTo(0));
- });
-
- test('should create only one bubble per shake', () {
- // This test would verify that handleShake() in ZenTapGame
- // creates exactly one bubble per shake event
-
- // The implementation should spawn exactly 1 bubble
- // (as opposed to the previous 2-4 bubbles)
- expect(true, isTrue); // Placeholder for actual implementation test
- });
- });
-
- group('Integration Tests', () {
- test('should maintain performance with all rules active', () {
- // Test that all three rules working together
- // don't negatively impact game performance
-
- // This would measure frame rates, memory usage, etc.
- // with all bubble rules active simultaneously
- expect(true, isTrue); // Placeholder
- });
-
- test('should handle edge cases gracefully', () {
- // Test scenarios like:
- // - Screen rotation during gameplay
- // - Very rapid shake events
- // - Many bubbles colliding simultaneously
- // - Low memory conditions
-
- expect(true, isTrue); // Placeholder
- });
- });
- });
-
- group('Bubble Rules Constants', () {
- test('should have correct constant values', () {
- // Verify all rule constants are set correctly
- expect(BubbleSpawner.bubbleMaxDiameter, equals(50.0));
- expect(BubbleSpawner.bubbleMinSpacing, equals(10.0));
- expect(BubbleSpawner.screenMargin, equals(120.0));
- expect(BubbleSpawner.uiTopMargin, equals(100.0));
-
- expect(Bubble.maxCollisions, equals(3));
- expect(Bubble.collisionGracePeriod, equals(2.0));
-
- // Note: Shake debounce time is private, but effect should be testable
- });
-
- test('should calculate effective bubble area correctly', () {
- const effectiveSize = BubbleSpawner.bubbleMaxDiameter + BubbleSpawner.bubbleMinSpacing;
- const expectedArea = effectiveSize * effectiveSize;
-
- expect(effectiveSize, equals(60.0)); // 50 + 10
- expect(expectedArea, equals(3600.0)); // 60 * 60
- });
- });
- }
- /// Helper class for testing bubble rules in isolation
- class MockGameContext {
- Vector2 size;
-
- MockGameContext(this.size);
-
- /// Simulate screen size change
- void resize(Vector2 newSize) {
- size = newSize;
- }
- }
- /// Test utilities for bubble rule validation
- class BubbleRulesTestUtils {
- /// Create a test bubble with specific parameters
- static Bubble createTestBubble({
- Vector2? position,
- bool isAutoSpawned = true,
- }) {
- return Bubble(
- position: position ?? Vector2(100, 100),
- isAutoSpawned: isAutoSpawned,
- );
- }
-
- /// Simulate collision between two bubbles
- static void simulateCollision(Bubble bubble1, Bubble bubble2) {
- // This would trigger the collision detection system
- // to test the triple collision rule
- }
-
- /// Simulate shake event with timing
- static void simulateShake(TiltDetector detector, {int? timestamp}) {
- // This would trigger shake detection
- // to test the single bubble per shake rule
- }
-
- /// Calculate expected max bubbles for given screen size
- static int calculateExpectedMaxBubbles(Vector2 screenSize) {
- const margin = BubbleSpawner.screenMargin;
- const uiMargin = BubbleSpawner.uiTopMargin;
- const effectiveSize = BubbleSpawner.bubbleMaxDiameter + BubbleSpawner.bubbleMinSpacing;
-
- final availableWidth = screenSize.x - (2 * margin);
- final availableHeight = screenSize.y - (2 * margin) - uiMargin;
-
- if (availableWidth <= 0 || availableHeight <= 0) return 4;
-
- final availableArea = availableWidth * availableHeight;
- final effectiveArea = effectiveSize * effectiveSize;
-
- final theoretical = (availableArea / effectiveArea).floor();
- return theoretical.clamp(4, 15);
- }
- }
|