mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-22 15:48:08 -05:00
Updated and revised unit tests (including new SongRegistry)
This commit is contained in:
parent
7e1c11bb25
commit
dfedaa8838
16 changed files with 3882 additions and 101 deletions
|
@ -7,7 +7,7 @@
|
|||
"note": {
|
||||
"assetPath": "shared:arrows",
|
||||
"scale": 1.0,
|
||||
"isPixel": true,
|
||||
"isPixel": false,
|
||||
"data": {
|
||||
"left": { "prefix": "noteLeft" },
|
||||
"down": { "prefix": "noteDown" },
|
||||
|
@ -19,7 +19,7 @@
|
|||
"assetPath": "shared:arrows",
|
||||
"scale": 1.0,
|
||||
"offsets": [28, 32],
|
||||
"isPixel": true,
|
||||
"isPixel": false,
|
||||
"data": {
|
||||
"leftStatic": { "prefix": "staticLeft0" },
|
||||
"leftPress": { "prefix": "pressedLeft0" },
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"songName": "Bopeebo",
|
||||
"artist": "Kawai Sprite",
|
||||
"timeFormat": "ms",
|
||||
"timeChanges": [{ "t": 0, "bpm": 100, "n": 4, "d": 4, "bt": [4, 4, 4, 4] }],
|
||||
"playData": {
|
||||
"songVariations": [],
|
||||
"difficulties": ["easy", "normal", "hard"],
|
||||
"playableChars": { "bf": { "g": "gf", "o": "dad" } },
|
||||
"stage": "mainStage",
|
||||
"noteSkin": "Normal"
|
||||
},
|
||||
"generatedBy": "MasterEric (by hand)"
|
||||
}
|
File diff suppressed because it is too large
Load diff
1738
tests/unit/assets/preload/data/songs/bopeebo/bopeebo-chart.json
Normal file
1738
tests/unit/assets/preload/data/songs/bopeebo/bopeebo-chart.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"songName": "Bopeebo",
|
||||
"artist": "Kawai Sprite",
|
||||
"timeFormat": "ms",
|
||||
"timeChanges": [{ "t": 0, "bpm": 100, "n": 4, "d": 4, "bt": [4, 4, 4, 4] }],
|
||||
"playData": {
|
||||
"songVariations": [],
|
||||
"difficulties": ["easy", "normal", "hard"],
|
||||
"playableChars": { "bf": { "g": "gf", "o": "dad" } },
|
||||
"stage": "mainStage",
|
||||
"noteSkin": "Normal"
|
||||
},
|
||||
"generatedBy": "MasterEric (by hand)"
|
||||
}
|
|
@ -44,11 +44,12 @@
|
|||
<!-- Assets -->
|
||||
<assets path="assets/preload" rename="assets" exclude="*.ogg" if="web" />
|
||||
<assets path="assets/preload" rename="assets" exclude="*.mp3" unless="web" />
|
||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg" if="web" />
|
||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3" unless="web" />
|
||||
<library name="shared" preload="true" />
|
||||
<!--
|
||||
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg" if="web" />
|
||||
<assets path="assets/songs" library="songs" exclude="*.fla|*.mp3" unless="web" />
|
||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg" if="web" />
|
||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3" unless="web" />
|
||||
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.ogg" if="web" />
|
||||
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.mp3" unless="web" />
|
||||
<assets path="assets/week1" library="week1" exclude="*.fla|*.ogg" if="web" />
|
||||
|
@ -68,7 +69,6 @@
|
|||
<assets path="assets/weekend1" library="weekend1" exclude="*.fla|*.ogg" if="web" />
|
||||
<assets path="assets/weekend1" library="weekend1" exclude="*.fla|*.mp3" unless="web" />
|
||||
<library name="songs" preload="true" />
|
||||
<library name="shared" preload="true" />
|
||||
<library name="tutorial" preload="true" />
|
||||
<library name="week1" preload="true" />
|
||||
<library name="week2" preload="true" />
|
||||
|
@ -87,8 +87,8 @@
|
|||
<haxedef name="FLX_RECORD" />
|
||||
|
||||
<!-- Clean up the output -->
|
||||
<haxedef name="no-traces" />
|
||||
<!--
|
||||
<haxedef name="echo-traces" />
|
||||
-->
|
||||
<haxedef name="ignore-inline" />
|
||||
<haxeflag name="-w" value="-WDeprecated" />
|
||||
|
|
|
@ -127,4 +127,54 @@ class FunkinAssert
|
|||
};
|
||||
validateThrows(targetFunc, predicate, info);
|
||||
}
|
||||
|
||||
static var capturedTraces:Array<String> = [];
|
||||
|
||||
public static function initAssertTrace():Void
|
||||
{
|
||||
var oldTrace = haxe.Log.trace;
|
||||
haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) {
|
||||
onTrace(v, infos);
|
||||
// oldTrace(v, infos);
|
||||
};
|
||||
}
|
||||
|
||||
public static function clearTraces():Void
|
||||
{
|
||||
capturedTraces = [];
|
||||
}
|
||||
|
||||
@:nullSafety(Off) // Why isn't haxe.std null-safe?
|
||||
static function onTrace(v:Dynamic, ?infos:haxe.PosInfos)
|
||||
{
|
||||
// var str:String = haxe.Log.formatOutput(v, infos);
|
||||
var str:String = Std.string(v);
|
||||
capturedTraces.push(str);
|
||||
|
||||
#if (sys && echo_traces)
|
||||
Sys.println('[TESTLOG] $str');
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the first string that was traced and validate it.
|
||||
* @param expected
|
||||
*/
|
||||
public static inline function assertTrace(expected:String):Void
|
||||
{
|
||||
var actual:Null<String> = capturedTraces.shift();
|
||||
Assert.isNotNull(actual);
|
||||
Assert.areEqual(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the first string that was traced and validate it.
|
||||
* @param expected
|
||||
*/
|
||||
public static inline function assertLastTrace(expected:String):Void
|
||||
{
|
||||
var actual:Null<String> = capturedTraces.pop();
|
||||
Assert.isNotNull(actual);
|
||||
Assert.areEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ class MockTest extends FunkinTest
|
|||
{
|
||||
// Test that mocking works.
|
||||
|
||||
var mockSprite = mockatoo.Mockatoo.mock(flixel.FlxSprite);
|
||||
var mockAnim = mockatoo.Mockatoo.mock(flixel.animation.FlxAnimationController);
|
||||
var mockSprite = Mockatoo.mock(flixel.FlxSprite);
|
||||
var mockAnim = Mockatoo.mock(flixel.animation.FlxAnimationController);
|
||||
mockSprite.animation = mockAnim;
|
||||
|
||||
var animData:funkin.data.animation.AnimationData =
|
||||
|
@ -44,12 +44,12 @@ class MockTest extends FunkinTest
|
|||
|
||||
// Verify that the method was called once.
|
||||
// If not, a VerificationException will be thrown and the test will fail.
|
||||
mockatoo.Mockatoo.verify(mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false), times(1));
|
||||
mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false).verify(times(1));
|
||||
|
||||
FunkinAssert.validateThrows(function() {
|
||||
// Attempt to verify the method was called.
|
||||
// This should FAIL, since we didn't call the method.
|
||||
mockatoo.Mockatoo.verify(mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false), times(1));
|
||||
mockAnim.addByPrefix("testAnim", "blablabla", 24, false, false, false).verify(times(1));
|
||||
}, function(err) {
|
||||
return Std.isOfType(err, mockatoo.exception.VerificationException);
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ package funkin;
|
|||
import flixel.FlxG;
|
||||
import flixel.FlxState;
|
||||
import funkin.Conductor;
|
||||
import funkin.play.song.SongData.SongTimeChange;
|
||||
import funkin.data.song.SongData.SongTimeChange;
|
||||
import funkin.util.Constants;
|
||||
import massive.munit.Assert;
|
||||
|
||||
|
@ -16,6 +16,8 @@ class ConductorTest extends FunkinTest
|
|||
@Before
|
||||
function before()
|
||||
{
|
||||
FunkinAssert.initAssertTrace();
|
||||
|
||||
resetGame();
|
||||
|
||||
// The ConductorState will advance the conductor when step() is called.
|
||||
|
@ -193,16 +195,7 @@ class ConductorTest extends FunkinTest
|
|||
function testSingleTimeChange():Void
|
||||
{
|
||||
// Start the song with a BPM of 120.
|
||||
var songTimeChanges:Array<SongTimeChange> = [
|
||||
{
|
||||
t: 0,
|
||||
b: 0,
|
||||
bpm: 120,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
}, // 120 bpm starting 0 sec/0 beats
|
||||
];
|
||||
var songTimeChanges:Array<SongTimeChange> = [new SongTimeChange(0, 120)];
|
||||
Conductor.mapTimeChanges(songTimeChanges);
|
||||
|
||||
// All should be at 0.
|
||||
|
@ -253,24 +246,7 @@ class ConductorTest extends FunkinTest
|
|||
function testDoubleTimeChange():Void
|
||||
{
|
||||
// Start the song with a BPM of 120.
|
||||
var songTimeChanges:Array<SongTimeChange> = [
|
||||
{
|
||||
t: 0,
|
||||
b: 0,
|
||||
bpm: 120,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
}, // 120 bpm starting 0 sec/0 beats
|
||||
{
|
||||
t: 3000,
|
||||
b: 6,
|
||||
bpm: 90,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
} // 90 bpm starting 3 sec/6 beats
|
||||
];
|
||||
var songTimeChanges:Array<SongTimeChange> = [new SongTimeChange(0, 120), new SongTimeChange(3000, 90)];
|
||||
Conductor.mapTimeChanges(songTimeChanges);
|
||||
|
||||
// All should be at 0.
|
||||
|
@ -354,30 +330,9 @@ class ConductorTest extends FunkinTest
|
|||
{
|
||||
// Start the song with a BPM of 120, then move to 90, then move to 180.
|
||||
var songTimeChanges:Array<SongTimeChange> = [
|
||||
{
|
||||
t: 0,
|
||||
b: null,
|
||||
bpm: 120,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
}, // 120 bpm starting 0 sec/0 beats
|
||||
{
|
||||
t: 3000,
|
||||
b: null,
|
||||
bpm: 90,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
}, // 90 bpm starting 3 sec/6 beats
|
||||
{
|
||||
t: 6000,
|
||||
b: null,
|
||||
bpm: 180,
|
||||
n: 4,
|
||||
d: 4,
|
||||
bt: [4, 4, 4, 4]
|
||||
} // 90 bpm starting 3 sec/6 beats
|
||||
new SongTimeChange(0, 120),
|
||||
new SongTimeChange(3000, 90),
|
||||
new SongTimeChange(6000, 180)
|
||||
];
|
||||
Conductor.mapTimeChanges(songTimeChanges);
|
||||
|
||||
|
|
|
@ -17,7 +17,10 @@ class BaseRegistryTest extends FunkinTest
|
|||
}
|
||||
|
||||
@BeforeClass
|
||||
public function beforeClass() {}
|
||||
public function beforeClass()
|
||||
{
|
||||
FunkinAssert.initAssertTrace();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public function afterClass() {}
|
||||
|
@ -118,7 +121,7 @@ class MyType implements IRegistryEntry<MyTypeData>
|
|||
return 'MyType($id)';
|
||||
}
|
||||
|
||||
public function _fetchData(id:String):Null<MyTypeData>
|
||||
static function _fetchData(id:String):Null<MyTypeData>
|
||||
{
|
||||
return MyTypeRegistry.instance.parseEntryDataWithMigration(id, MyTypeRegistry.instance.fetchEntryVersion(id));
|
||||
}
|
||||
|
@ -153,17 +156,18 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<MyTypeData>();
|
||||
var jsonStr:String = loadEntryFile(id);
|
||||
|
||||
parser.fromJson(jsonStr);
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
parser.fromJson(contents, fileName);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
{
|
||||
trace('[${registryId}] Failed to parse entry data: ${id}');
|
||||
for (error in parser.errors)
|
||||
{
|
||||
trace(error);
|
||||
}
|
||||
printErrors(parser.errors, id);
|
||||
return null;
|
||||
}
|
||||
return parser.value;
|
||||
|
@ -177,31 +181,33 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<MyTypeData_v0_1_x>();
|
||||
var jsonStr:String = loadEntryFile(id);
|
||||
|
||||
parser.fromJson(jsonStr);
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
parser.fromJson(contents, fileName);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
{
|
||||
trace('[${registryId}] Failed to parse entry data: ${id}');
|
||||
for (error in parser.errors)
|
||||
{
|
||||
trace(error);
|
||||
}
|
||||
printErrors(parser.errors, id);
|
||||
return null;
|
||||
}
|
||||
|
||||
var oldData:MyTypeData_v0_1_x = parser.value;
|
||||
return migrateData_v0_1_x(oldData);
|
||||
}
|
||||
|
||||
var result:MyTypeData =
|
||||
function migrateData_v0_1_x(input:MyTypeData_v0_1_x):MyTypeData
|
||||
{
|
||||
return {
|
||||
version: DATA_VERSION,
|
||||
id: '${oldData.id}',
|
||||
name: oldData.name,
|
||||
id: '${input.id}',
|
||||
name: input.name,
|
||||
data: []
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override function parseEntryDataWithMigration(id:String, version:thx.semver.Version):Null<MyTypeData>
|
||||
|
|
|
@ -123,9 +123,12 @@ class LevelRegistryTest extends FunkinTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Requires redoing validation.")
|
||||
public function testCreateEntryBlankPath():Void
|
||||
{
|
||||
// Using @:jcustomparse, `titleAsset` has a validation function that ensures it is not blank.
|
||||
// This test makes sure that the validation function is being called, and that the error
|
||||
// results in the level failing to parse.
|
||||
|
||||
FunkinAssert.validateThrows(function() {
|
||||
var result:Null<Level> = LevelRegistry.instance.createEntry("blankpathtest");
|
||||
}, function(err) {
|
||||
|
@ -134,7 +137,6 @@ class LevelRegistryTest extends FunkinTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Requires redoing validation.")
|
||||
public function testFetchBadEntry():Void
|
||||
{
|
||||
var result:Null<Level> = LevelRegistry.instance.fetchEntry("blablabla");
|
||||
|
|
|
@ -86,7 +86,7 @@ class NoteStyleRegistryTest extends FunkinTest
|
|||
@Test
|
||||
public function testFetchDefault():Void
|
||||
{
|
||||
var nsrMock:NoteStyleRegistry = mock(NoteStyleRegistry);
|
||||
var nsrMock = Mockatoo.mock(NoteStyleRegistry);
|
||||
|
||||
nsrMock.fetchDefault().callsRealMethod();
|
||||
|
||||
|
|
133
tests/unit/source/funkin/data/song/SongRegistryTest.hx
Normal file
133
tests/unit/source/funkin/data/song/SongRegistryTest.hx
Normal file
|
@ -0,0 +1,133 @@
|
|||
package funkin.data.song;
|
||||
|
||||
import funkin.data.song.SongData;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.play.song.Song;
|
||||
import massive.munit.Assert;
|
||||
import massive.munit.async.AsyncFactory;
|
||||
import massive.munit.util.Timer;
|
||||
|
||||
@:nullSafety
|
||||
@:access(funkin.play.song.Song)
|
||||
@:access(funkin.data.song.SongRegistry)
|
||||
class SongRegistryTest extends FunkinTest
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public function beforeClass():Void
|
||||
{
|
||||
FunkinAssert.initAssertTrace();
|
||||
SongRegistry.instance.loadEntries();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public function afterClass():Void {}
|
||||
|
||||
@Before
|
||||
public function setup():Void {}
|
||||
|
||||
@After
|
||||
public function tearDown():Void {}
|
||||
|
||||
@Test
|
||||
public function testValid():Void
|
||||
{
|
||||
Assert.isNotNull(SongRegistry.instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public function testParseMetadata():Void
|
||||
{
|
||||
var result:Null<SongData.SongMetadata> = SongRegistry.instance.parseEntryMetadata("bopeebo");
|
||||
|
||||
Assert.isNotNull(result);
|
||||
|
||||
var expectedVersion:thx.semver.Version = "2.0.0";
|
||||
Assert.areEqual(expectedVersion, result.version);
|
||||
Assert.areEqual("Bopeebo", result.songName);
|
||||
Assert.areEqual("Kawai Sprite", result.artist);
|
||||
Assert.areEqual(SongData.SongTimeFormat.MILLISECONDS, result.timeFormat);
|
||||
Assert.areEqual("MasterEric (by hand)", result.generatedBy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public function testParseChartData():Void
|
||||
{
|
||||
var result:Null<SongData.SongChartData> = SongRegistry.instance.parseEntryChartData("bopeebo");
|
||||
|
||||
Assert.isNotNull(result);
|
||||
|
||||
var expectedVersion:thx.semver.Version = "2.0.0";
|
||||
Assert.areEqual(expectedVersion, result.version);
|
||||
}
|
||||
|
||||
/**
|
||||
* A test validating an error is thrown when attempting to parse chart data as metadata.
|
||||
*/
|
||||
@Test
|
||||
public function testParseMetadataSwapped():Void
|
||||
{
|
||||
// Arrange
|
||||
FunkinAssert.clearTraces();
|
||||
|
||||
// Act
|
||||
var result:Null<SongData.SongMetadata> = SongRegistry.instance.parseEntryMetadata("bopeebo-swapped");
|
||||
|
||||
// Assert
|
||||
Assert.isNull(result);
|
||||
FunkinAssert.assertTrace("[SONG] Failed to parse entry data: bopeebo-swapped");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"scrollSpeed\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:3");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"events\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:7");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"notes\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:185");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"songName\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:1738");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"timeFormat\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:1738");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"timeChanges\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:1738");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"playData\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:1738");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"artist\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-metadata.json:1738");
|
||||
}
|
||||
|
||||
/**
|
||||
* A test validating an error is thrown when attempting to parse metadata as chart data.
|
||||
*/
|
||||
@Test
|
||||
public function testParseChartDataSwapped():Void
|
||||
{
|
||||
// Arrange
|
||||
FunkinAssert.clearTraces();
|
||||
|
||||
// Act
|
||||
var result:Null<SongData.SongChartData> = SongRegistry.instance.parseEntryChartData("bopeebo-swapped");
|
||||
|
||||
// Assert
|
||||
Assert.isNull(result);
|
||||
FunkinAssert.assertTrace("[SONG] Failed to parse entry data: bopeebo-swapped");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"songName\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:3");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"artist\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:4");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"timeFormat\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:5");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"timeChanges\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:6");
|
||||
FunkinAssert.assertTrace(" Unknown variable \"playData\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:7");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"notes\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:15");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"events\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:15");
|
||||
FunkinAssert.assertTrace(" Uninitialized variable \"scrollSpeed\"");
|
||||
FunkinAssert.assertTrace(" at assets/data/songs/bopeebo-swapped/bopeebo-swapped-chart.json:15");
|
||||
}
|
||||
}
|
|
@ -1,11 +1,18 @@
|
|||
package funkin.play.notes.notestyle;
|
||||
|
||||
import flixel.util.FlxSort;
|
||||
import funkin.util.SortUtil;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.graphics.frames.FlxFrame;
|
||||
import flixel.graphics.frames.FlxFramesCollection;
|
||||
import massive.munit.util.Timer;
|
||||
import massive.munit.Assert;
|
||||
import massive.munit.async.AsyncFactory;
|
||||
import funkin.data.notestyle.NoteStyleRegistry;
|
||||
import funkin.play.notes.notestyle.NoteStyle;
|
||||
import flixel.animation.FlxAnimationController;
|
||||
import openfl.utils.Assets;
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
@:access(funkin.play.notes.notestyle.NoteStyle)
|
||||
class NoteStyleTest extends FunkinTest
|
||||
|
@ -31,20 +38,142 @@ class NoteStyleTest extends FunkinTest
|
|||
public function tearDown() {}
|
||||
|
||||
@Test
|
||||
@Ignore("This test doesn't work, crashes when the project has 2 mocks of the same class???")
|
||||
public function testBuildNoteSprite()
|
||||
{
|
||||
var target:Null<NoteStyle> = NoteStyleRegistry.instance.fetchEntry("funkin");
|
||||
|
||||
Assert.isNotNull(target);
|
||||
|
||||
var mockNoteSprite:NoteSprite = mock(NoteSprite);
|
||||
// var mockAnim = mock(FlxAnimationController);
|
||||
// mockNoteSprite.animation = mockAnim;
|
||||
// Arrange
|
||||
var mockNoteSprite = Mockatoo.mock(NoteSprite);
|
||||
var mockAnim = Mockatoo.mock(FlxAnimationController);
|
||||
var scale = new FlxPoint(1, 1); // handle sprite.scale.x on the mock
|
||||
|
||||
mockNoteSprite.animation = mockAnim; // Tell the mock to forward calls to the animation controller mock.
|
||||
mockNoteSprite.scale.returns(scale); // Redirect this final variable to a local variable.
|
||||
mockNoteSprite.antialiasing.callsRealMethod(); // Tell the mock to treat this like a normal property.
|
||||
mockNoteSprite.frames.callsRealMethod(); // Tell the mock to treat this like a normal property.
|
||||
|
||||
// Act
|
||||
target.buildNoteSprite(mockNoteSprite);
|
||||
|
||||
Assert.areEqual(mockNoteSprite.frames, []);
|
||||
var expectedGraphic:FlxGraphic = FlxG.bitmap.add("shared:assets/shared/images/arrows.png");
|
||||
|
||||
// Assert
|
||||
Assert.isNotNull(mockNoteSprite.frames);
|
||||
mockNoteSprite.frames.frames.sort(SortUtil.byFrameName);
|
||||
var frameCount:Int = mockNoteSprite.frames.frames.length;
|
||||
Assert.areEqual(24, frameCount);
|
||||
|
||||
// Validate each frame.
|
||||
for (i in 0...frameCount)
|
||||
{
|
||||
var currentFrame:FlxFrame = mockNoteSprite.frames.frames[i];
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
Assert.areEqual("confirmDown0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 1:
|
||||
Assert.areEqual("confirmDown0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 2:
|
||||
Assert.areEqual("confirmLeft0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 3:
|
||||
Assert.areEqual("confirmLeft0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 4:
|
||||
Assert.areEqual("confirmRight0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 5:
|
||||
Assert.areEqual("confirmRight0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 6:
|
||||
Assert.areEqual("confirmUp0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 7:
|
||||
Assert.areEqual("confirmUp0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 8:
|
||||
Assert.areEqual("noteDown0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 9:
|
||||
Assert.areEqual("noteLeft0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 10:
|
||||
Assert.areEqual("noteRight0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 11:
|
||||
Assert.areEqual("noteUp0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 12:
|
||||
Assert.areEqual("pressedDown0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 13:
|
||||
Assert.areEqual("pressedDown0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 14:
|
||||
Assert.areEqual("pressedLeft0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 15:
|
||||
Assert.areEqual("pressedLeft0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 16:
|
||||
Assert.areEqual("pressedRight0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 17:
|
||||
Assert.areEqual("pressedRight0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 18:
|
||||
Assert.areEqual("pressedUp0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 19:
|
||||
Assert.areEqual("pressedUp0002", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 20:
|
||||
Assert.areEqual("staticDown0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 21:
|
||||
Assert.areEqual("staticLeft0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 22:
|
||||
Assert.areEqual("staticRight0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
case 23:
|
||||
Assert.areEqual("staticUp0001", currentFrame.name);
|
||||
Assert.areEqual(expectedGraphic, currentFrame.parent);
|
||||
default:
|
||||
Assert.fail('Got unexpected frame number ${i}');
|
||||
}
|
||||
}
|
||||
|
||||
// Verify animations were applied.
|
||||
@:privateAccess {
|
||||
mockAnim.addByPrefix('purpleScroll', 'noteLeft', 24, false, false, false).verify(times(1));
|
||||
mockAnim.addByPrefix('blueScroll', 'noteDown', 24, false, false, false).verify(times(1));
|
||||
mockAnim.addByPrefix('greenScroll', 'noteUp', 24, false, false, false).verify(times(1));
|
||||
mockAnim.addByPrefix('redScroll', 'noteRight', 24, false, false, false).verify(times(1));
|
||||
mockAnim.destroyAnimations().verify(times(1));
|
||||
mockAnim.set_frameIndex(0).verify(times(1));
|
||||
// Verify there were no other functions called.
|
||||
mockAnim.verifyZeroInteractions();
|
||||
}
|
||||
|
||||
// Verify sprite was initialized.
|
||||
@:privateAccess {
|
||||
mockNoteSprite.set_graphic(expectedGraphic).verify(times(1));
|
||||
mockNoteSprite.graphicLoaded().verify(times(1));
|
||||
mockNoteSprite.set_antialiasing(true).verify(times(1));
|
||||
mockNoteSprite.set_frames(mockNoteSprite.frames).verify(times(1));
|
||||
mockNoteSprite.set_frame(mockNoteSprite.frames.frames[21]).verify(times(1));
|
||||
mockNoteSprite.resetHelpers().verify(times(1));
|
||||
|
||||
Assert.areEqual(1, mockNoteSprite.scale.x);
|
||||
Assert.areEqual(1, mockNoteSprite.scale.y);
|
||||
// Verify there were no other functions called.
|
||||
mockNoteSprite.verifyZeroInteractions();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -3,7 +3,7 @@ package funkin.util;
|
|||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.util.FlxSort;
|
||||
import funkin.play.song.SongData.SongNoteData;
|
||||
import funkin.data.song.SongData.SongNoteData;
|
||||
import massive.munit.util.Timer;
|
||||
import massive.munit.Assert;
|
||||
import massive.munit.async.AsyncFactory;
|
||||
|
|
|
@ -34,8 +34,8 @@ class FlxAnimationUtilTest extends FunkinTest
|
|||
public function testAddAtlasAnimation()
|
||||
{
|
||||
// Build a mock child class of FlxSprite
|
||||
var mockSprite = mock(FlxSprite);
|
||||
var mockAnim = mock(FlxAnimationController);
|
||||
var mockSprite = Mockatoo.mock(FlxSprite);
|
||||
var mockAnim = Mockatoo.mock(FlxAnimationController);
|
||||
mockSprite.animation = mockAnim;
|
||||
|
||||
var animData:AnimationData =
|
||||
|
@ -85,8 +85,8 @@ class FlxAnimationUtilTest extends FunkinTest
|
|||
public function testAddAtlasAnimations()
|
||||
{
|
||||
// Build a mock child class of FlxSprite
|
||||
var mockSprite = mock(FlxSprite);
|
||||
var mockAnim = mock(FlxAnimationController);
|
||||
var mockSprite = Mockatoo.mock(FlxSprite);
|
||||
var mockAnim = Mockatoo.mock(FlxAnimationController);
|
||||
mockSprite.animation = mockAnim;
|
||||
|
||||
var animData:Array<AnimationData> = [
|
||||
|
|
Loading…
Reference in a new issue