Files
flutter_lua_runtime/test/runtime/models/runtime_node_test.dart
2026-06-07 22:53:58 +08:00

325 lines
9.3 KiB
Dart

import 'package:flame_lua_runtime/runtime/models/runtime_node.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('RuntimeNode', () {
test('parses required and optional fields', () {
final node = RuntimeNode.fromMap({
'id': 'dice_button',
'type': 'button',
'parent': 'top_bar',
'asset': 'dice_normal',
'pressedAsset': 'dice_pressed',
'disabledAsset': 'dice_disabled',
'animation': 'idle',
'skin': 'red',
'loop': false,
'text': 'Roll',
'x': 10,
'y': 20.5,
'width': 120,
'height': 48,
'paddingLeft': 4,
'paddingTop': 5,
'paddingRight': 6,
'paddingBottom': 7,
'anchor': 'center',
'layer': 3,
'visible': false,
'alpha': 0.7,
'scale': 1.2,
'rotation': 0.4,
'color': '#112233',
'fontSize': 18,
'textAlign': 'left',
'radius': 10,
'strokeWidth': 3,
'value': 0.6,
'scrollX': 15,
'scrollY': 20,
'contentWidth': 220,
'contentHeight': 180,
'virtualized': true,
'cacheExtent': 12,
'inertia': false,
'scrollbarThumbColor': '#abcdef',
'scrollbarTrackColor': '#123456',
'scrollbarThickness': 6,
'scrollbarVisible': false,
'interactive': true,
'onTap': 'roll_dice',
'onScroll': 'list_scrolled',
'preset': 'burst',
'count': 32,
'duration': 0.6,
'speedMin': 60,
'speedMax': 180,
'gravityX': 0,
'gravityY': 120,
'spread': 360,
'colorTo': '#00ffcc33',
'radiusTo': 0,
'autoRemove': false,
'fadeOut': false,
});
expect(node.id, 'dice_button');
expect(node.type, 'button');
expect(node.parent, 'top_bar');
expect(node.asset, 'dice_normal');
expect(node.pressedAsset, 'dice_pressed');
expect(node.disabledAsset, 'dice_disabled');
expect(node.animation, 'idle');
expect(node.skin, 'red');
expect(node.loop, isFalse);
expect(node.text, 'Roll');
expect(node.x, 10);
expect(node.y, 20.5);
expect(node.width, 120);
expect(node.height, 48);
expect(node.paddingLeft, 4);
expect(node.paddingTop, 5);
expect(node.paddingRight, 6);
expect(node.paddingBottom, 7);
expect(node.anchor, 'center');
expect(node.layer, 3);
expect(node.visible, isFalse);
expect(node.alpha, 0.7);
expect(node.scale, 1.2);
expect(node.rotation, 0.4);
expect(node.color, const Color(0xff112233));
expect(node.fontSize, 18);
expect(node.textAlign, 'left');
expect(node.radius, 10);
expect(node.strokeWidth, 3);
expect(node.value, 0.6);
expect(node.scrollX, 15);
expect(node.scrollY, 20);
expect(node.contentWidth, 220);
expect(node.contentHeight, 180);
expect(node.virtualized, isTrue);
expect(node.cacheExtent, 12);
expect(node.inertia, isFalse);
expect(node.scrollbarThumbColor, const Color(0xffabcdef));
expect(node.scrollbarTrackColor, const Color(0xff123456));
expect(node.scrollbarThickness, 6);
expect(node.scrollbarVisible, isFalse);
expect(node.interactive, isTrue);
expect(node.onTap, 'roll_dice');
expect(node.onScroll, 'list_scrolled');
expect(node.preset, 'burst');
expect(node.count, 32);
expect(node.duration, 0.6);
expect(node.speedMin, 60);
expect(node.speedMax, 180);
expect(node.gravityX, 0);
expect(node.gravityY, 120);
expect(node.spread, 360);
expect(node.colorTo, const Color(0x00ffcc33));
expect(node.radiusTo, 0);
expect(node.autoRemove, isFalse);
expect(node.fadeOut, isFalse);
});
test('applies default values', () {
final node = RuntimeNode.fromMap({'id': 'label', 'type': 'text'});
expect(node.x, 0);
expect(node.y, 0);
expect(node.anchor, 'topLeft');
expect(node.layer, 0);
expect(node.visible, isTrue);
expect(node.alpha, 1);
expect(node.scale, 1);
expect(node.rotation, 0);
expect(node.loop, isTrue);
expect(node.textAlign, 'center');
expect(node.scrollbarVisible, isTrue);
expect(node.paddingLeft, 0);
expect(node.paddingTop, 0);
expect(node.paddingRight, 0);
expect(node.paddingBottom, 0);
expect(node.autoRemove, isTrue);
expect(node.fadeOut, isTrue);
expect(node.interactive, isFalse);
});
test('copies only provided props', () {
final node = RuntimeNode.fromMap({
'id': 'piece',
'type': 'circle',
'x': 1,
'y': 2,
'color': '#ff0000',
});
final updated = node.copyWithProps({
'x': 20,
'parent': 'board',
'visible': false,
'color': '#8000ff00',
'radius': 8,
'strokeWidth': 2,
'value': 0.75,
'width': 70,
'height': 60,
'paddingLeft': 8,
'paddingTop': 9,
'paddingRight': 10,
'paddingBottom': 11,
'contentWidth': 120,
'contentHeight': 100,
'pressedAsset': 'button_pressed',
'disabledAsset': 'button_disabled',
'scrollX': 90,
'scrollY': 80,
'textAlign': 'right',
'preset': 'trail',
'count': 12,
});
expect(updated.id, 'piece');
expect(updated.type, 'circle');
expect(updated.parent, 'board');
expect(updated.x, 20);
expect(updated.y, 2);
expect(updated.visible, isFalse);
expect(updated.color, const Color(0x8000ff00));
expect(updated.radius, 8);
expect(updated.strokeWidth, 2);
expect(updated.value, 0.75);
expect(updated.width, 70);
expect(updated.height, 60);
expect(updated.paddingLeft, 8);
expect(updated.paddingTop, 9);
expect(updated.paddingRight, 10);
expect(updated.paddingBottom, 11);
expect(updated.contentWidth, 120);
expect(updated.contentHeight, 100);
expect(updated.pressedAsset, 'button_pressed');
expect(updated.disabledAsset, 'button_disabled');
expect(updated.scrollX, 68);
expect(updated.scrollY, 60);
expect(updated.textAlign, 'right');
expect(updated.preset, 'trail');
expect(updated.count, 12);
});
test('rejects invalid values', () {
expect(
() => RuntimeNode.fromMap({'id': '', 'type': 'text'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'text', 'x': 'bad'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'text', 'color': 'red'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'unknown'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'text',
'anchor': 'middle',
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'progress', 'value': 2}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'text',
'textAlign': 'justify',
}),
throwsFormatException,
);
expect(
() =>
RuntimeNode.fromMap({'id': 'a', 'type': 'listView', 'scrollY': -1}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'particle',
'preset': 'unknown',
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'particle', 'count': 0}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'listView',
'paddingTop': -1,
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'listView',
'cacheExtent': -1,
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'rect',
'interactive': 'yes',
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'button',
'pressedAsset': 1,
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'rect', 'parent': 1}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'spine', 'loop': 'yes'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({'id': 'a', 'type': 'rect', 'parent': 'a'}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'rect',
'interative': true,
}),
throwsFormatException,
);
expect(
() => RuntimeNode.fromMap({
'id': 'a',
'type': 'rect',
}).copyWithProps({'screenWitdh': 720}),
throwsFormatException,
);
});
});
}