From 09fc0f2b21f2472a4ed58924a971243841b1c818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20=C5=A0imon=C3=ADk?= <32575328+ryzizub@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:28:26 +0100 Subject: [PATCH] test: Add coverage in `flame_texturepacker` (#3432) Add additional tests to flame_texturepacker --- packages/flame_texturepacker/pubspec.yaml | 1 + .../test/flame_texturepacker_test.dart | 69 +++++++++ .../test/legacy_format_test.dart | 107 ++++++++++++- .../test/new_format_test.dart | 144 +++++++++++++++++- 4 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 packages/flame_texturepacker/test/flame_texturepacker_test.dart diff --git a/packages/flame_texturepacker/pubspec.yaml b/packages/flame_texturepacker/pubspec.yaml index 17da0e03fc6..eea2aa93a0b 100644 --- a/packages/flame_texturepacker/pubspec.yaml +++ b/packages/flame_texturepacker/pubspec.yaml @@ -24,3 +24,4 @@ dev_dependencies: flame_lint: ^1.2.1 flutter_test: sdk: flutter + mocktail: ^1.0.4 diff --git a/packages/flame_texturepacker/test/flame_texturepacker_test.dart b/packages/flame_texturepacker/test/flame_texturepacker_test.dart new file mode 100644 index 00000000000..93e356b5bde --- /dev/null +++ b/packages/flame_texturepacker/test/flame_texturepacker_test.dart @@ -0,0 +1,69 @@ +import 'dart:io'; + +import 'package:flame/cache.dart'; +import 'package:flame/flame.dart'; +import 'package:flame/game.dart'; +import 'package:flame_texturepacker/flame_texturepacker.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class _MockAssetBundle extends Mock implements AssetBundle {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('TexturepackerLoader', () { + const atlasPath = + 'test/assets/newFormat/multiplePages/MultiplePageAtlasMap.atlas'; + const atlasImage1 = + 'test/assets/newFormat/multiplePages/MultiplePageAtlasMap.png'; + + test('load atlas from storage', () async { + final flameGame = FlameGame(); + final atlas = await flameGame.atlasFromStorage(atlasPath); + + expect(atlas, isNotNull); + expect(atlas.sprites.length, equals(12)); + + final firstSprite = atlas.findSpriteByName('robot_walk'); + expect(firstSprite, isNotNull); + expect(firstSprite!.srcSize, isNotNull); + expect(firstSprite.srcPosition, isNotNull); + }); + + test('load atlas from assets', () async { + final bundle = _MockAssetBundle(); + when(() => bundle.loadString(any())) + .thenAnswer((_) async => File(atlasPath).readAsString()); + when(() => bundle.load(any())).thenAnswer( + (_) async => ByteData.sublistView( + File(atlasImage1).readAsBytesSync(), + ), + ); + + final flameGame = FlameGame(); + Flame.assets = AssetsCache(bundle: bundle, prefix: ''); + Flame.images = Images(bundle: bundle, prefix: ''); + + final atlas = await flameGame.atlasFromAssets(atlasPath); + + expect(atlas, isNotNull); + expect(atlas.sprites.length, equals(12)); + + final firstSprite = atlas.findSpriteByName('robot_walk'); + expect(firstSprite, isNotNull); + expect(firstSprite!.srcSize.x, greaterThan(0)); + expect(firstSprite.srcSize.y, greaterThan(0)); + expect(firstSprite.srcPosition, isNotNull); + }); + + test('throws exception for invalid atlas path', () async { + final flameGame = FlameGame(); + expect( + () => flameGame.atlasFromStorage('invalid_path.atlas'), + throwsException, + ); + }); + }); +} diff --git a/packages/flame_texturepacker/test/legacy_format_test.dart b/packages/flame_texturepacker/test/legacy_format_test.dart index 82d8cd11c97..050688f01ec 100644 --- a/packages/flame_texturepacker/test/legacy_format_test.dart +++ b/packages/flame_texturepacker/test/legacy_format_test.dart @@ -1,7 +1,12 @@ +import 'dart:math' as math; +import 'dart:ui'; + import 'package:flame/components.dart'; import 'package:flame_texturepacker/flame_texturepacker.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class _MockCanvas extends Mock implements Canvas {} void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -59,6 +64,7 @@ void main() { expect(jumpSprite.srcSize, Vector2(192, 256)); expect(jumpSprite.originalSize, Vector2(192, 256)); expect(jumpSprite.offset, Vector2(0, 0)); + expect(jumpSprite.angle, math.pi / 2); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, false); @@ -75,6 +81,7 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(0, 0)); + expect(walkSprite.angle, 0); }); test('Trimmed sprite data is loaded correctly', () async { @@ -98,12 +105,14 @@ void main() { expect(idleSprite.srcSize, Vector2(192, 256)); expect(idleSprite.originalSize, Vector2(192, 256)); expect(idleSprite.offset, Vector2(31, 0)); + expect(idleSprite.angle, 0); final idleSpritePackedSize = idleSprite.clone(useOriginalSize: false); expect(idleSpritePackedSize.src, const Rect.fromLTWH(0, 310, 130, 182)); expect(idleSpritePackedSize.srcSize, Vector2(130, 182)); expect(idleSpritePackedSize.originalSize, Vector2(130, 182)); expect(idleSpritePackedSize.offset, Vector2(0, 0)); + expect(idleSpritePackedSize.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, true); @@ -120,12 +129,14 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(14, 2)); + expect(walkSprite.angle, math.pi / 2); final walkSpritePackedSize = walkSprite.clone(useOriginalSize: false); expect(walkSpritePackedSize.src, const Rect.fromLTWH(0, 0, 183, 150)); expect(walkSpritePackedSize.srcSize, Vector2(150, 183)); expect(walkSpritePackedSize.originalSize, Vector2(150, 183)); expect(walkSpritePackedSize.offset, Vector2(0, 0)); + expect(walkSpritePackedSize.angle, math.pi / 2); }); }); group('Single page atlas', () { @@ -159,6 +170,15 @@ void main() { expect(jumpSprite, isNotNull); }); + test('findSpriteByNameIndex will return 1 sprite', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + final jumpSprite = atlas.findSpriteByNameIndex('robot_jump', -1); + expect(jumpSprite, isNotNull); + }); + test('Sprite data is loaded correctly', () async { final atlas = await TexturePackerAtlas.load( atlasPath, @@ -180,6 +200,7 @@ void main() { expect(jumpSprite.srcSize, Vector2(192, 256)); expect(jumpSprite.originalSize, Vector2(192, 256)); expect(jumpSprite.offset, Vector2(0, 0)); + expect(jumpSprite.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, false); @@ -196,6 +217,7 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(0, 0)); + expect(walkSprite.angle, 0); }); test('Trimmed sprite data is loaded correctly', () async { @@ -219,12 +241,14 @@ void main() { expect(idleSprite.srcSize, Vector2(192, 256)); expect(idleSprite.originalSize, Vector2(192, 256)); expect(idleSprite.offset, Vector2(31, 0)); + expect(idleSprite.angle, 0); final idleSpritePackedSize = idleSprite.clone(useOriginalSize: false); expect(idleSpritePackedSize.src, const Rect.fromLTWH(0, 160, 130, 182)); expect(idleSpritePackedSize.srcSize, Vector2(130, 182)); expect(idleSpritePackedSize.originalSize, Vector2(130, 182)); expect(idleSpritePackedSize.offset, Vector2(0, 0)); + expect(idleSpritePackedSize.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, true); @@ -241,12 +265,93 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(14, 2)); + expect(walkSprite.angle, math.pi / 2); final walkSpritePackedSize = walkSprite.clone(useOriginalSize: false); expect(walkSpritePackedSize.src, const Rect.fromLTWH(191, 367, 183, 150)); expect(walkSpritePackedSize.srcSize, Vector2(150, 183)); expect(walkSpritePackedSize.originalSize, Vector2(150, 183)); expect(walkSpritePackedSize.offset, Vector2(0, 0)); + expect(walkSpritePackedSize.angle, math.pi / 2); + }); + + test('Sprite renders correctly when not rotated', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(384, 512), + ); + + expect(sprite.rotate, false); + expect(sprite.offset, Vector2.zero()); + expect(sprite.originalSize, Vector2(192, 256)); + expect(sprite.srcSize, Vector2(192, 256)); + }); + + test('Sprite renders correctly when rotated', () async { + final atlas = await TexturePackerAtlas.load( + atlasTrimmedPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_walk')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(384, 512), + ); + + expect(sprite.rotate, true); + expect(sprite.offset, Vector2(14, 2)); + expect(sprite.originalSize, Vector2(192, 256)); + expect(sprite.srcSize, Vector2(192, 256)); + expect(sprite.angle, math.pi / 2); + }); + + test('Sprite renders with correct anchor point', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(192, 256), + anchor: Anchor.center, + ); + + expect(sprite.originalSize, Vector2(192, 256)); + }); + + test('Sprite renders correctly with default position', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + size: Vector2(192, 256), + ); + + expect(sprite.originalSize, Vector2(192, 256)); }); }); } diff --git a/packages/flame_texturepacker/test/new_format_test.dart b/packages/flame_texturepacker/test/new_format_test.dart index 0785e6e768e..f77ae76aa3b 100644 --- a/packages/flame_texturepacker/test/new_format_test.dart +++ b/packages/flame_texturepacker/test/new_format_test.dart @@ -1,7 +1,12 @@ +import 'dart:math' as math; +import 'dart:ui'; + import 'package:flame/components.dart'; import 'package:flame_texturepacker/flame_texturepacker.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class _MockCanvas extends Mock implements Canvas {} void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -37,6 +42,15 @@ void main() { expect(jumpSprite, isNotNull); }); + test('findSpriteByNameIndex will return 1 sprite', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + final jumpSprite = atlas.findSpriteByNameIndex('robot_jump', -1); + expect(jumpSprite, isNotNull); + }); + test('Sprite data is loaded correctly', () async { final atlas = await TexturePackerAtlas.load( atlasPath, @@ -58,6 +72,7 @@ void main() { expect(jumpSprite.srcSize, Vector2(192, 256)); expect(jumpSprite.originalSize, Vector2(192, 256)); expect(jumpSprite.offset, Vector2(0, 0)); + expect(jumpSprite.angle, math.pi / 2); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, false); @@ -74,6 +89,7 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(0, 0)); + expect(walkSprite.angle, 0); }); test('Trimmed sprite data is loaded correctly', () async { final atlas = await TexturePackerAtlas.load( @@ -96,12 +112,14 @@ void main() { expect(idleSprite.srcSize, Vector2(192, 256)); expect(idleSprite.originalSize, Vector2(192, 256)); expect(idleSprite.offset, Vector2(31, 0)); + expect(idleSprite.angle, 0); final idleSpritePackedSize = idleSprite.clone(useOriginalSize: false); expect(idleSpritePackedSize.src, const Rect.fromLTWH(0, 310, 130, 182)); expect(idleSpritePackedSize.srcSize, Vector2(130, 182)); expect(idleSpritePackedSize.originalSize, Vector2(130, 182)); expect(idleSpritePackedSize.offset, Vector2(0, 0)); + expect(idleSpritePackedSize.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, true); @@ -118,12 +136,72 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(14, 2)); + expect(walkSprite.angle, math.pi / 2); final walkSpritePackedSize = walkSprite.clone(useOriginalSize: false); expect(walkSpritePackedSize.src, const Rect.fromLTWH(0, 0, 183, 150)); expect(walkSpritePackedSize.srcSize, Vector2(150, 183)); expect(walkSpritePackedSize.originalSize, Vector2(150, 183)); expect(walkSpritePackedSize.offset, Vector2(0, 0)); + expect(walkSpritePackedSize.angle, math.pi / 2); + }); + + test('Sprite renders correctly', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(384, 512), + ); + + expect(sprite.rotate, true); + expect(sprite.offset, Vector2.zero()); + expect(sprite.originalSize, Vector2(192, 256)); + expect(sprite.srcSize, Vector2(192, 256)); + expect(sprite.angle, math.pi / 2); + }); + + test('Sprite renders with correct anchor point', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(192, 256), + anchor: Anchor.center, + ); + + expect(sprite.originalSize, Vector2(192, 256)); + }); + + test('Sprite renders correctly with default position', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + size: Vector2(192, 256), + ); + + expect(sprite.originalSize, Vector2(192, 256)); }); }); @@ -180,6 +258,7 @@ void main() { expect(jumpSprite.srcSize, Vector2(192, 256)); expect(jumpSprite.originalSize, Vector2(192, 256)); expect(jumpSprite.offset, Vector2(0, 0)); + expect(jumpSprite.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, false); @@ -196,6 +275,7 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(0, 0)); + expect(walkSprite.angle, 0); }); test('Trimmed sprite data is loaded correctly', () async { final atlas = await TexturePackerAtlas.load( @@ -218,12 +298,14 @@ void main() { expect(idleSprite.srcSize, Vector2(192, 256)); expect(idleSprite.originalSize, Vector2(192, 256)); expect(idleSprite.offset, Vector2(31, 0)); + expect(idleSprite.angle, 0); final idleSpritePackedSize = idleSprite.clone(useOriginalSize: false); expect(idleSpritePackedSize.src, const Rect.fromLTWH(0, 160, 130, 182)); expect(idleSpritePackedSize.srcSize, Vector2(130, 182)); expect(idleSpritePackedSize.originalSize, Vector2(130, 182)); expect(idleSpritePackedSize.offset, Vector2(0, 0)); + expect(idleSpritePackedSize.angle, 0); final walkSprite = atlas.findSpriteByName('robot_walk')!; expect(walkSprite.rotate, true); @@ -240,12 +322,72 @@ void main() { expect(walkSprite.srcSize, Vector2(192, 256)); expect(walkSprite.originalSize, Vector2(192, 256)); expect(walkSprite.offset, Vector2(14, 2)); + expect(walkSprite.angle, math.pi / 2); final walkSpritePackedSize = walkSprite.clone(useOriginalSize: false); expect(walkSpritePackedSize.src, const Rect.fromLTWH(191, 367, 183, 150)); expect(walkSpritePackedSize.srcSize, Vector2(150, 183)); expect(walkSpritePackedSize.originalSize, Vector2(150, 183)); expect(walkSpritePackedSize.offset, Vector2(0, 0)); + expect(walkSpritePackedSize.angle, math.pi / 2); + }); + + test('Sprite renders correctly', () async { + final atlas = await TexturePackerAtlas.load( + atlasTrimmedPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_walk')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(384, 512), + ); + + expect(sprite.rotate, true); + expect(sprite.offset, Vector2(14, 2)); + expect(sprite.originalSize, Vector2(192, 256)); + expect(sprite.srcSize, Vector2(192, 256)); + expect(sprite.angle, math.pi / 2); + }); + + test('Sprite renders with correct anchor point', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + position: Vector2(100, 100), + size: Vector2(192, 256), + anchor: Anchor.center, + ); + + expect(sprite.originalSize, Vector2(192, 256)); + }); + + test('Sprite renders correctly with default position', () async { + final atlas = await TexturePackerAtlas.load( + atlasPath, + fromStorage: true, + ); + + final sprite = atlas.findSpriteByName('robot_jump')!; + final canvas = _MockCanvas(); + + sprite.render( + canvas, + size: Vector2(192, 256), + ); + + expect(sprite.originalSize, Vector2(192, 256)); }); }); }