diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT.bytes b/UnityProject/Assets/HotUpdate/Compiled/AOT.bytes index 4172a286e..89250dab9 100644 Binary files a/UnityProject/Assets/HotUpdate/Compiled/AOT.bytes and b/UnityProject/Assets/HotUpdate/Compiled/AOT.bytes differ diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT/Assembly-CSharp.dll.bytes b/UnityProject/Assets/HotUpdate/Compiled/AOT/Assembly-CSharp.dll.bytes index 0120cb169..3e08fe13e 100644 Binary files a/UnityProject/Assets/HotUpdate/Compiled/AOT/Assembly-CSharp.dll.bytes and b/UnityProject/Assets/HotUpdate/Compiled/AOT/Assembly-CSharp.dll.bytes differ diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.Core.dll.bytes b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.Core.dll.bytes index bc107bb36..5aa4c62dc 100644 Binary files a/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.Core.dll.bytes and b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.Core.dll.bytes differ diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes new file mode 100644 index 000000000..40b39cc00 Binary files /dev/null and b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes differ diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes.meta b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes.meta new file mode 100644 index 000000000..b38753fe8 --- /dev/null +++ b/UnityProject/Assets/HotUpdate/Compiled/AOT/JEngine.UI.dll.bytes.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 96713b8f9d5a8459d9a234a94b98aad7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/HotUpdate/Compiled/AOT/mscorlib.dll.bytes b/UnityProject/Assets/HotUpdate/Compiled/AOT/mscorlib.dll.bytes index e3b0d3f87..b09729798 100644 Binary files a/UnityProject/Assets/HotUpdate/Compiled/AOT/mscorlib.dll.bytes and b/UnityProject/Assets/HotUpdate/Compiled/AOT/mscorlib.dll.bytes differ diff --git a/UnityProject/Assets/HotUpdate/Compiled/HotUpdate.Code.dll.bytes b/UnityProject/Assets/HotUpdate/Compiled/HotUpdate.Code.dll.bytes index 0ebb5054e..2e4a6742f 100644 Binary files a/UnityProject/Assets/HotUpdate/Compiled/HotUpdate.Code.dll.bytes and b/UnityProject/Assets/HotUpdate/Compiled/HotUpdate.Code.dll.bytes differ diff --git a/UnityProject/Assets/HybridCLRGenerate/AOTGenericReferences.cs b/UnityProject/Assets/HybridCLRGenerate/AOTGenericReferences.cs index 1a95bfabf..601b35eae 100644 --- a/UnityProject/Assets/HybridCLRGenerate/AOTGenericReferences.cs +++ b/UnityProject/Assets/HybridCLRGenerate/AOTGenericReferences.cs @@ -231,6 +231,7 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour // System.Func> // System.Func> // System.Func + // System.Func> // System.Func // System.Func // System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter>>>>>> diff --git a/UnityProject/Assets/HybridCLRGenerate/link.xml b/UnityProject/Assets/HybridCLRGenerate/link.xml index d24d8f726..40c1f37a7 100644 --- a/UnityProject/Assets/HybridCLRGenerate/link.xml +++ b/UnityProject/Assets/HybridCLRGenerate/link.xml @@ -3,7 +3,7 @@ - + @@ -60,6 +60,7 @@ + diff --git a/UnityProject/Assets/Obfuz/SymbolObfus/symbol-mapping.xml b/UnityProject/Assets/Obfuz/SymbolObfus/symbol-mapping.xml index 2044b3eca..38ff1638c 100644 --- a/UnityProject/Assets/Obfuz/SymbolObfus/symbol-mapping.xml +++ b/UnityProject/Assets/Obfuz/SymbolObfus/symbol-mapping.xml @@ -6,10 +6,9 @@ - - + @@ -23,13 +22,13 @@ - + - + @@ -44,7 +43,9 @@ + + @@ -108,11 +109,11 @@ - - - + + + @@ -210,8 +211,8 @@ - - + + @@ -225,14 +226,14 @@ - + - + @@ -429,22 +430,18 @@ + - - - - - @@ -452,7 +449,6 @@ - @@ -460,15 +456,9 @@ - - - - - - @@ -478,7 +468,7 @@ - + @@ -500,12 +490,9 @@ - - - @@ -515,27 +502,19 @@ - - - - - - - - @@ -570,13 +549,13 @@ - + - + @@ -593,6 +572,8 @@ + + @@ -606,6 +587,7 @@ + @@ -614,23 +596,23 @@ - - - - - - - - + + + + + + + + - - - - - - + + + + + + @@ -713,6 +695,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -763,6 +767,16 @@ + + + + + + + + + + @@ -827,6 +841,19 @@ + + + + + + + + + + + + + @@ -894,6 +921,19 @@ + + + + + + + + + + + + + @@ -905,7 +945,6 @@ - @@ -963,6 +1002,17 @@ + + + + + + + + + + + @@ -1027,6 +1077,14 @@ + + + + + + + + @@ -1120,6 +1178,22 @@ + + + + + + + + + + + + + + + + @@ -1486,6 +1560,13 @@ + + + + + + + diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle deleted file mode 100644 index cc2cf699c..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle deleted file mode 100644 index 726588b2e..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle deleted file mode 100644 index 728781068..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle new file mode 100644 index 000000000..61e6aa1fc Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle.meta similarity index 74% rename from UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle.meta rename to UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle.meta index 22d1db087..30b76022e 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/20c6686ce660502e16a881f74dde76d7.bundle.meta +++ b/UnityProject/Assets/StreamingAssets/yoo/main/427571ab4f40f72802eba023fca7a5e8.bundle.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 20f1c68c092344d9db47d271ac501b70 +guid: de5e734b7a33942bd9654e699dacc44c DefaultImporter: externalObjects: {} userData: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle new file mode 100644 index 000000000..4c68bf650 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle.meta similarity index 74% rename from UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle.meta rename to UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle.meta index 6b923b73b..dbcbd6f19 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/15ce485b672a77a1aa540ef46e39dd60.bundle.meta +++ b/UnityProject/Assets/StreamingAssets/yoo/main/4549b29fd00b2e57f75873c7c370340b.bundle.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c1e21a37cd285485b8f1dd31b30e4cfd +guid: 2174447b3e3b0476d812642fafebd053 DefaultImporter: externalObjects: {} userData: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle deleted file mode 100644 index 1d0ef8d6f..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle new file mode 100644 index 000000000..2ef062de8 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle.meta similarity index 74% rename from UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle.meta rename to UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle.meta index 8ea2b12ce..96074e337 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/490ed19cf4dd5e128fb13cf883211456.bundle.meta +++ b/UnityProject/Assets/StreamingAssets/yoo/main/5154722f17ed26abd07f0275b2fb315c.bundle.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 847a5be1e4ca4483aa16db998484f462 +guid: 5243d056b9ae74f9fbaa56e844dc828a DefaultImporter: externalObjects: {} userData: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle deleted file mode 100644 index 25496770c..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle.meta deleted file mode 100644 index 06891e5f5..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/56d90d09aba519ecd1cba11dfc31f5d8.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 71eeae5c5480a43beb21881fcab30067 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle new file mode 100644 index 000000000..786243cd1 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle.meta similarity index 74% rename from UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle.meta rename to UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle.meta index 273eddccf..d9a18d087 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/1832d193ad604c285e2456ba2a7855c7.bundle.meta +++ b/UnityProject/Assets/StreamingAssets/yoo/main/578aebd507ab15c1f73f9a41b5962e15.bundle.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d69d6db128d434954a13ab04606b4745 +guid: 9e41401d7b056451bbff4a803d6a9851 DefaultImporter: externalObjects: {} userData: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle new file mode 100644 index 000000000..2262543fa Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle.meta new file mode 100644 index 000000000..7d3e1566d --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/743303a92561c811cf9e428d59f4eed5.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 81bbcfd248fb343c28dac65c33d43001 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle new file mode 100644 index 000000000..e3b710e08 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle.meta new file mode 100644 index 000000000..1705d5547 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/76c5d9ebda370e318d1d711bf29db391.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 212dfe20022f74ecd8320d07a2ab2c47 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle new file mode 100644 index 000000000..ca5fd5145 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle.meta new file mode 100644 index 000000000..f873a455d --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/7d008b589c7529b71f703107fc14b2a1.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 958812791c38144aa81c7b1b1524183d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle deleted file mode 100644 index a81da76d3..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle.meta deleted file mode 100644 index eff1e6e67..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/85bf7a8000e78a0640dd575c462d71de.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 27a669f4ef6574563bacb09b7ee138f9 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.bytes b/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.bytes index 9731d5032..f45f9ca03 100644 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.bytes and b/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.bytes differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.json b/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.json index 3b379666a..6ff076070 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.json +++ b/UnityProject/Assets/StreamingAssets/yoo/main/BuildinCatalog.json @@ -1,59 +1,59 @@ { "FileVersion": "1.0.0", "PackageName": "main", - "PackageVersion": "260122842", + "PackageVersion": "260202209", "Wrappers": [ { - "BundleGUID": "15ce485b672a77a1aa540ef46e39dd60", - "FileName": "15ce485b672a77a1aa540ef46e39dd60.bundle" + "BundleGUID": "427571ab4f40f72802eba023fca7a5e8", + "FileName": "427571ab4f40f72802eba023fca7a5e8.bundle" }, { - "BundleGUID": "1832d193ad604c285e2456ba2a7855c7", - "FileName": "1832d193ad604c285e2456ba2a7855c7.bundle" + "BundleGUID": "4549b29fd00b2e57f75873c7c370340b", + "FileName": "4549b29fd00b2e57f75873c7c370340b.bundle" }, { - "BundleGUID": "20c6686ce660502e16a881f74dde76d7", - "FileName": "20c6686ce660502e16a881f74dde76d7.bundle" + "BundleGUID": "5154722f17ed26abd07f0275b2fb315c", + "FileName": "5154722f17ed26abd07f0275b2fb315c.bundle" }, { - "BundleGUID": "490ed19cf4dd5e128fb13cf883211456", - "FileName": "490ed19cf4dd5e128fb13cf883211456.bundle" + "BundleGUID": "578aebd507ab15c1f73f9a41b5962e15", + "FileName": "578aebd507ab15c1f73f9a41b5962e15.bundle" }, { - "BundleGUID": "56d90d09aba519ecd1cba11dfc31f5d8", - "FileName": "56d90d09aba519ecd1cba11dfc31f5d8.bundle" + "BundleGUID": "743303a92561c811cf9e428d59f4eed5", + "FileName": "743303a92561c811cf9e428d59f4eed5.bundle" }, { - "BundleGUID": "85bf7a8000e78a0640dd575c462d71de", - "FileName": "85bf7a8000e78a0640dd575c462d71de.bundle" + "BundleGUID": "76c5d9ebda370e318d1d711bf29db391", + "FileName": "76c5d9ebda370e318d1d711bf29db391.bundle" }, { - "BundleGUID": "ae16386504461146b4ec88eabc7de89f", - "FileName": "ae16386504461146b4ec88eabc7de89f.bundle" + "BundleGUID": "7d008b589c7529b71f703107fc14b2a1", + "FileName": "7d008b589c7529b71f703107fc14b2a1.bundle" }, { - "BundleGUID": "c4964674a708bf22bbb753ca23c93aec", - "FileName": "c4964674a708bf22bbb753ca23c93aec.bundle" + "BundleGUID": "a99f206109faf44e637346323f255c84", + "FileName": "a99f206109faf44e637346323f255c84.bundle" }, { - "BundleGUID": "c792026eb6f717273422cfb875e3121d", - "FileName": "c792026eb6f717273422cfb875e3121d.bundle" + "BundleGUID": "aa7811a04dda58d98435ef7170ce0828", + "FileName": "aa7811a04dda58d98435ef7170ce0828.bundle" }, { - "BundleGUID": "c9cd151a5606eec7bf47ac8d9401fb94", - "FileName": "c9cd151a5606eec7bf47ac8d9401fb94.bundle" + "BundleGUID": "bd7a40533fe708ab184ec75ceac853ee", + "FileName": "bd7a40533fe708ab184ec75ceac853ee.bundle" }, { - "BundleGUID": "cde787d0afee29507a54189b7372cf14", - "FileName": "cde787d0afee29507a54189b7372cf14.bundle" + "BundleGUID": "e578f9b5397d53f41a2b284805860df8", + "FileName": "e578f9b5397d53f41a2b284805860df8.bundle" }, { - "BundleGUID": "dcb1b5ed74667265ec98799a1576d5d3", - "FileName": "dcb1b5ed74667265ec98799a1576d5d3.bundle" + "BundleGUID": "e6ed0b286414267962e71c6bd3e19aae", + "FileName": "e6ed0b286414267962e71c6bd3e19aae.bundle" }, { - "BundleGUID": "ec451612fae802d07094821d3808809f", - "FileName": "ec451612fae802d07094821d3808809f.bundle" + "BundleGUID": "eb53152c634d44794e4aebca15ee8b0b", + "FileName": "eb53152c634d44794e4aebca15ee8b0b.bundle" } ] } \ No newline at end of file diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle new file mode 100644 index 000000000..ed26b2c15 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle.meta new file mode 100644 index 000000000..851e0121a --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/a99f206109faf44e637346323f255c84.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2958988901cfc434b80f4be6803f2476 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle new file mode 100644 index 000000000..5a9273183 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle.meta new file mode 100644 index 000000000..200b376c0 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/aa7811a04dda58d98435ef7170ce0828.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 40e342c01cb18476a95a4e9594d40050 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle deleted file mode 100644 index b9fc0ab4b..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle.meta deleted file mode 100644 index 0c207d50b..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/ae16386504461146b4ec88eabc7de89f.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4c402c51c1cfb486db858688a858bc2a -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle new file mode 100644 index 000000000..3df9048f8 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle.meta new file mode 100644 index 000000000..98d786a16 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/bd7a40533fe708ab184ec75ceac853ee.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f4fdff4e1398e4a5885baa7fc28a455c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle deleted file mode 100644 index 7b52c82c3..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle.meta deleted file mode 100644 index 69127d37e..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/c4964674a708bf22bbb753ca23c93aec.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a751ff6081a0e47f7896e6d81f05dbd4 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle deleted file mode 100644 index 2f4ca6735..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle.meta deleted file mode 100644 index c75b32233..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/c792026eb6f717273422cfb875e3121d.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: bc024ff87285a4d70b9bdc36db09affb -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle deleted file mode 100644 index 68c3c340a..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle.meta deleted file mode 100644 index fc32c00bb..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/c9cd151a5606eec7bf47ac8d9401fb94.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 2278ffb3a86fa46bd9ec779d9e3570bc -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle deleted file mode 100644 index 5df889a71..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle.meta deleted file mode 100644 index ef4b59b0e..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/cde787d0afee29507a54189b7372cf14.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e6e583689c4b748fb95baf175223ab01 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle deleted file mode 100644 index 1f488cbf9..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle.meta deleted file mode 100644 index a147ada29..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/dcb1b5ed74667265ec98799a1576d5d3.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: f38ecdd44fd244182b4ce83a37f9f5d9 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle new file mode 100644 index 000000000..58728e098 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle.meta new file mode 100644 index 000000000..ca8b57254 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/e578f9b5397d53f41a2b284805860df8.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5c1eb87919ebe47b1a06e08655a3bc2c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle new file mode 100644 index 000000000..fddb219c2 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle.meta new file mode 100644 index 000000000..48f835839 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/e6ed0b286414267962e71c6bd3e19aae.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a84b9fbe1723d4e4fae407b37fe9fbed +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle new file mode 100644 index 000000000..3a4706dd6 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle.meta new file mode 100644 index 000000000..acd97f688 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/eb53152c634d44794e4aebca15ee8b0b.bundle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ef03bf55664ca498e91aedd1b9fd485c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle b/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle deleted file mode 100644 index d1eece83b..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle.meta b/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle.meta deleted file mode 100644 index 0a7271550..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/ec451612fae802d07094821d3808809f.bundle.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a2d173b47a4d24b59967eb0fdb96eb9c -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main.version b/UnityProject/Assets/StreamingAssets/yoo/main/main.version index ffa7a9d22..c18b98797 100644 --- a/UnityProject/Assets/StreamingAssets/yoo/main/main.version +++ b/UnityProject/Assets/StreamingAssets/yoo/main/main.version @@ -1 +1 @@ -260122842 \ No newline at end of file +260202209 \ No newline at end of file diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes b/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes deleted file mode 100644 index 0459cdad2..000000000 Binary files a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes and /dev/null differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes.meta b/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes.meta deleted file mode 100644 index 71739ced1..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.bytes.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 1e8bd8dcd1a294734a049a2fae181b7e -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash b/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash deleted file mode 100644 index 8a6afc97a..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash +++ /dev/null @@ -1 +0,0 @@ -79054da8 \ No newline at end of file diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash.meta b/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash.meta deleted file mode 100644 index 10237fb8d..000000000 --- a/UnityProject/Assets/StreamingAssets/yoo/main/main_260122842.hash.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 005fc6e6cd6d149b5b8fed516ceee7f4 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes new file mode 100644 index 000000000..44af77e89 Binary files /dev/null and b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes differ diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes.meta b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes.meta new file mode 100644 index 000000000..d2f2440d8 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.bytes.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e54223704c94c4bb5a1affe8058d803d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash new file mode 100644 index 000000000..684ea60dd --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash @@ -0,0 +1 @@ +7f2ba677 \ No newline at end of file diff --git a/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash.meta b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash.meta new file mode 100644 index 000000000..e64e2a6f0 --- /dev/null +++ b/UnityProject/Assets/StreamingAssets/yoo/main/main_260202209.hash.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 24256b48ddcbd492892edc790e8f209c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime/MessageBox.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime/MessageBox.cs index df7cfb0d7..6b6aefdaf 100644 --- a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime/MessageBox.cs +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime/MessageBox.cs @@ -123,6 +123,12 @@ private static GameObject Prefab /// When true, simulates prefab being unavailable. Used for testing "no prefab" error handling. /// internal static bool SimulateNoPrefab; + + /// + /// When true, skips DontDestroyOnLoad call. Required for EditMode tests since + /// DontDestroyOnLoad only works in PlayMode. + /// + internal static bool SkipDontDestroyOnLoad; #endif #if UNITY_INCLUDE_TESTS @@ -462,7 +468,12 @@ private void Init(string title, string content, string ok, string no) // Set initial state for animation and play it GameObject.transform.localScale = InitialScale; - Object.DontDestroyOnLoad(GameObject); +#if UNITY_EDITOR + if (!SkipDontDestroyOnLoad) +#endif + { + Object.DontDestroyOnLoad(GameObject); + } } private T GetComponent(string path) where T : Component diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs index 61003bcbc..7c32d6241 100644 --- a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs @@ -319,5 +319,143 @@ public void Constructor_PopupFieldHasZeroMargins() } #endregion + + #region Child Composition Tests + + [Test] + public void Constructor_HasSingleChild() + { + var dropdown = new JDropdown(_choices); + + // The PopupField should be the only child + Assert.AreEqual(1, dropdown.childCount); + Assert.AreSame(dropdown.PopupField, dropdown.ElementAt(0)); + } + + [Test] + public void Constructor_PopupFieldIsChild() + { + Assert.IsTrue(_dropdown.Contains(_dropdown.PopupField)); + } + + [Test] + public void Constructor_AppliesInputContainerStyle() + { + // Verify flexGrow and flexShrink are applied (from JTheme.ApplyInputContainerStyle) + Assert.AreEqual(1f, _dropdown.style.flexGrow.value); + Assert.AreEqual(1f, _dropdown.style.flexShrink.value); + } + + #endregion + + #region Formatter Tests + + [Test] + public void GenericDropdown_WithNullFormatter_UsesToString() + { + var choices = new List { 1, 2, 3 }; + var dropdown = new JDropdown(choices, 1, null, null); + + // Should not throw and should work + Assert.AreEqual(1, dropdown.Value); + } + + [Test] + public void GenericDropdown_WithCustomFormatters_AcceptsBoth() + { + var choices = new List { 1, 2, 3 }; + + // Custom formatters for display + Func formatSelected = v => $"Selected: {v}"; + Func formatList = v => $"Option {v}"; + + var dropdown = new JDropdown(choices, 1, formatSelected, formatList); + + Assert.IsNotNull(dropdown); + Assert.AreEqual(1, dropdown.Value); + } + + [Test] + public void GenericDropdown_FormattersHandleNull() + { + // Test with nullable type-like behavior using reference types + var choices = new List { "One", "Two", null }; + var dropdown = new JDropdown(choices, "One"); + + Assert.AreEqual("One", dropdown.Value); + } + + #endregion + + #region Edge Cases + + [Test] + public void Choices_SetToNewList_UpdatesDropdown() + { + var newChoices = new List { "NewA", "NewB", "NewC" }; + _dropdown.Choices = newChoices; + + Assert.AreEqual(3, _dropdown.Choices.Count); + Assert.Contains("NewA", _dropdown.Choices); + } + + [Test] + public void Value_SetToFirstChoice_Works() + { + _dropdown.Value = "Option1"; + Assert.AreEqual("Option1", _dropdown.Value); + } + + [Test] + public void Value_SetToLastChoice_Works() + { + _dropdown.Value = "Option3"; + Assert.AreEqual("Option3", _dropdown.Value); + } + + [Test] + public void OnValueChanged_CanBeSetToNull() + { + Assert.DoesNotThrow(() => _dropdown.OnValueChanged(null)); + } + + [Test] + public void OnValueChanged_MultipleRegistrations_DoNotThrow() + { + Assert.DoesNotThrow(() => + { + _dropdown.OnValueChanged(v => { }); + _dropdown.OnValueChanged(v => { }); + }); + } + + #endregion + + #region ForEnum Edge Cases + + [Test] + public void ForEnum_DefaultValue_IsFirstEnumValue() + { + var dropdown = JDropdown.ForEnum(); + // Default should be the first enum value + Assert.AreEqual(ButtonVariant.Primary, dropdown.Value); + } + + [Test] + public void ForEnum_CanChangeValueMultipleTimes() + { + var dropdown = JDropdown.ForEnum(); + + dropdown.Value = ButtonVariant.Success; + Assert.AreEqual(ButtonVariant.Success, dropdown.Value); + + dropdown.Value = ButtonVariant.Danger; + Assert.AreEqual(ButtonVariant.Danger, dropdown.Value); + + dropdown.Value = ButtonVariant.Primary; + Assert.AreEqual(ButtonVariant.Primary, dropdown.Value); + } + + #endregion } } diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs index ba35522df..27fcd0a28 100644 --- a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs @@ -2,8 +2,9 @@ // EditMode unit tests for JObjectField using NUnit.Framework; -using UnityEngine; +using UnityEditor; using UnityEditor.UIElements; +using UnityEngine; using JEngine.UI.Editor.Components.Form; namespace JEngine.UI.Tests.Editor.Components.Form @@ -221,5 +222,44 @@ public void Constructor_InternalObjectFieldHasZeroMargins() } #endregion + + #region Child Composition Tests + + [Test] + public void Constructor_HasSingleChild() + { + var field = new JObjectField(); + + // The ObjectField should be the only child + Assert.AreEqual(1, field.childCount); + Assert.AreSame(field.ObjectField, field.ElementAt(0)); + } + + [Test] + public void Constructor_ObjectFieldIsChild() + { + Assert.IsTrue(_objectField.Contains(_objectField.ObjectField)); + } + + [Test] + public void Constructor_AppliesInputContainerStyle() + { + // Verify flexGrow and flexShrink are applied (from JTheme.ApplyInputContainerStyle) + Assert.AreEqual(1f, _objectField.style.flexGrow.value); + Assert.AreEqual(1f, _objectField.style.flexShrink.value); + } + + #endregion + + #region BindProperty Tests + + [Test] + public void BindProperty_MethodExists() + { + // Verify the method exists and is accessible + Assert.IsNotNull((System.Action)_objectField.BindProperty); + } + + #endregion } } diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs index 33e8340c9..909f5ab2a 100644 --- a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs @@ -2,6 +2,7 @@ // EditMode unit tests for JTextField using NUnit.Framework; +using UnityEditor; using UnityEngine.UIElements; using JEngine.UI.Editor.Components.Form; @@ -263,5 +264,93 @@ public void Constructor_InternalTextFieldHasZeroMargins() } #endregion + + #region Child Composition Tests + + [Test] + public void Constructor_HasSingleChild() + { + var field = new JTextField(); + + // The TextField should be the only child + Assert.AreEqual(1, field.childCount); + Assert.AreSame(field.TextField, field.ElementAt(0)); + } + + [Test] + public void Constructor_TextFieldIsChild() + { + Assert.IsTrue(_textField.Contains(_textField.TextField)); + } + + [Test] + public void Constructor_AppliesInputContainerStyle() + { + // Verify flexGrow and flexShrink are applied (from JTheme.ApplyInputContainerStyle) + Assert.AreEqual(1f, _textField.style.flexGrow.value); + Assert.AreEqual(1f, _textField.style.flexShrink.value); + } + + #endregion + + #region BindProperty Tests + + [Test] + public void BindProperty_MethodExists() + { + // Verify the method exists and is accessible + Assert.IsNotNull((System.Action)_textField.BindProperty); + } + + #endregion + + #region Placeholder Tests + + [Test] + public void Constructor_WithNullPlaceholder_DoesNotThrow() + { + Assert.DoesNotThrow(() => new JTextField("", null)); + } + + [Test] + public void Constructor_WithEmptyPlaceholder_DoesNotThrow() + { + Assert.DoesNotThrow(() => new JTextField("value", "")); + } + + [Test] + public void Constructor_WithLongPlaceholder_DoesNotThrow() + { + Assert.DoesNotThrow(() => new JTextField("", "This is a very long placeholder text")); + } + + #endregion + + #region Edge Cases + + [Test] + public void Value_WithSpecialCharacters_Works() + { + _textField.Value = "Hello\nWorld\t!"; + Assert.AreEqual("Hello\nWorld\t!", _textField.Value); + } + + [Test] + public void Value_WithUnicode_Works() + { + _textField.Value = "日本語テスト 🎮"; + Assert.AreEqual("日本語テスト 🎮", _textField.Value); + } + + [Test] + public void SetReadOnly_And_SetMultiline_CanBeCombined() + { + _textField.SetReadOnly(true).SetMultiline(true); + + Assert.IsTrue(_textField.TextField.isReadOnly); + Assert.IsTrue(_textField.TextField.multiline); + } + + #endregion } } diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs new file mode 100644 index 000000000..585927fd8 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs @@ -0,0 +1,66 @@ +// EditorUIRegistrationTests.cs +// EditMode unit tests for EditorUIRegistration + +using NUnit.Framework; +using JEngine.Core.Editor.CustomEditor; +using JEngine.UI.Editor.Internal; + +namespace JEngine.UI.Tests.Editor.Internal +{ + /// + /// Tests for . + /// Since EditorUIRegistration uses [InitializeOnLoad], the static constructor + /// runs automatically when the editor loads, before these tests execute. + /// + [TestFixture] + public class EditorUIRegistrationTests + { + #region Handler Registration Tests + + [Test] + public void CreatePanelContentHandler_IsRegistered() + { + // EditorUIRegistration sets Panel.CreatePanelContentHandler in its static constructor + Assert.IsNotNull(Panel.CreatePanelContentHandler, + "Panel.CreatePanelContentHandler should be registered by EditorUIRegistration"); + } + + [Test] + public void CreateInspectorHandler_IsRegistered() + { + // EditorUIRegistration sets BootstrapEditor.CreateInspectorHandler in its static constructor + Assert.IsNotNull(BootstrapEditor.CreateInspectorHandler, + "BootstrapEditor.CreateInspectorHandler should be registered by EditorUIRegistration"); + } + + [Test] + public void CreatePanelContentHandler_PointsToPanelUI() + { + // Verify the handler points to PanelUI.CreateContent + Assert.AreEqual( + nameof(PanelUI.CreateContent), + Panel.CreatePanelContentHandler.Method.Name, + "CreatePanelContentHandler should point to PanelUI.CreateContent"); + Assert.AreEqual( + typeof(PanelUI), + Panel.CreatePanelContentHandler.Method.DeclaringType, + "CreatePanelContentHandler should be declared in PanelUI"); + } + + [Test] + public void CreateInspectorHandler_PointsToBootstrapEditorUI() + { + // Verify the handler points to BootstrapEditorUI.CreateInspector + Assert.AreEqual( + nameof(BootstrapEditorUI.CreateInspector), + BootstrapEditor.CreateInspectorHandler.Method.Name, + "CreateInspectorHandler should point to BootstrapEditorUI.CreateInspector"); + Assert.AreEqual( + typeof(BootstrapEditorUI), + BootstrapEditor.CreateInspectorHandler.Method.DeclaringType, + "CreateInspectorHandler should be declared in BootstrapEditorUI"); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs.meta new file mode 100644 index 000000000..112e66575 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Internal/EditorUIRegistrationTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 779f66f0059384e2886e78c1cb99b6df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/MessageBoxTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/MessageBoxTests.cs index 5ac6d3e2a..e8ed4d584 100644 --- a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/MessageBoxTests.cs +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/MessageBoxTests.cs @@ -19,6 +19,7 @@ public override void BaseSetUp() MessageBox.Dispose(); MessageBox.TestHandler = null; MessageBox.SimulateNoPrefab = false; + MessageBox.SkipDontDestroyOnLoad = true; // Required for EditMode tests } [TearDown] @@ -28,6 +29,7 @@ public override void BaseTearDown() MessageBox.Dispose(); MessageBox.TestHandler = null; MessageBox.SimulateNoPrefab = false; + MessageBox.SkipDontDestroyOnLoad = false; } #region Static State Tests @@ -530,5 +532,239 @@ public IEnumerator CloseAll_AfterMultipleShows_ClearsAll() => UniTask.ToCoroutin }); #endregion + + #region Real MessageBox Tests (with prefab) + + [UnityTest] + public IEnumerator Show_WithRealPrefab_IncreasesActiveCount() => UniTask.ToCoroutine(async () => + { + // Don't set TestHandler - use real implementation + var initialActive = MessageBox.ActiveCount; + + // Start showing (don't await - we need to interact with it) + var showTask = MessageBox.Show("Test Title", "Test Content"); + + // Give it a frame to create + await UniTask.Yield(); + + // Active count should have increased + Assert.Greater(MessageBox.ActiveCount, initialActive); + + // Clean up by simulating OK click + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_ReturnsTrue_WhenOkClicked() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + MessageBox.TestSimulateButtonClick(true); + bool result = await showTask; + + Assert.IsTrue(result); + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_ReturnsFalse_WhenNoClicked() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + MessageBox.TestSimulateButtonClick(false); + bool result = await showTask; + + Assert.IsFalse(result); + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_SetsCorrectContent() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("My Title", "My Content", "Yes", "No"); + await UniTask.Yield(); + + var content = MessageBox.TestGetContent(); + Assert.IsNotNull(content); + Assert.AreEqual("My Title", content.Value.title); + Assert.AreEqual("My Content", content.Value.content); + Assert.AreEqual("Yes", content.Value.okText); + Assert.AreEqual("No", content.Value.noText); + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_BothButtonsVisible_ByDefault() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + var visibility = MessageBox.TestGetButtonVisibility(); + Assert.IsNotNull(visibility); + Assert.IsTrue(visibility.Value.okVisible); + Assert.IsTrue(visibility.Value.noVisible); + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_HidesOkButton_WhenOkIsNull() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content", null, "Cancel"); + await UniTask.Yield(); + + var visibility = MessageBox.TestGetButtonVisibility(); + Assert.IsNotNull(visibility); + Assert.IsFalse(visibility.Value.okVisible); + Assert.IsTrue(visibility.Value.noVisible); + + MessageBox.TestSimulateButtonClick(false); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_HidesNoButton_WhenNoIsNull() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content", "OK", null); + await UniTask.Yield(); + + var visibility = MessageBox.TestGetButtonVisibility(); + Assert.IsNotNull(visibility); + Assert.IsTrue(visibility.Value.okVisible); + Assert.IsFalse(visibility.Value.noVisible); + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_DefaultsToOk_WhenBothButtonsNull() => UniTask.ToCoroutine(async () => + { + // When both buttons are null/empty, should default to showing OK button + var showTask = MessageBox.Show("Test", "Content", null, null); + await UniTask.Yield(); + + var visibility = MessageBox.TestGetButtonVisibility(); + Assert.IsNotNull(visibility); + Assert.IsTrue(visibility.Value.okVisible); // Should default to OK + Assert.IsFalse(visibility.Value.noVisible); + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_ReturnsToPool_AfterClose() => UniTask.ToCoroutine(async () => + { + var initialPooled = MessageBox.PooledCount; + + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + MessageBox.TestSimulateButtonClick(true); + await showTask; + + // Should be in pool now + Assert.Greater(MessageBox.PooledCount, initialPooled); + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_ReusesPooledInstance() => UniTask.ToCoroutine(async () => + { + // First show - creates new instance + var showTask1 = MessageBox.Show("Test1", "Content1"); + await UniTask.Yield(); + MessageBox.TestSimulateButtonClick(true); + await showTask1; + + int pooledAfterFirst = MessageBox.PooledCount; + Assert.Greater(pooledAfterFirst, 0); + + // Second show - should reuse pooled instance + var showTask2 = MessageBox.Show("Test2", "Content2"); + await UniTask.Yield(); + + // Pool count should have decreased (instance taken from pool) + Assert.Less(MessageBox.PooledCount, pooledAfterFirst); + + MessageBox.TestSimulateButtonClick(true); + await showTask2; + }); + + [UnityTest] + public IEnumerator CloseAll_WithRealPrefab_ClosesAllActive() => UniTask.ToCoroutine(async () => + { + // Show multiple boxes without awaiting (use discard to suppress unused variable warning) + _ = MessageBox.Show("Test1", "Content1"); + await UniTask.Yield(); + _ = MessageBox.Show("Test2", "Content2"); + await UniTask.Yield(); + + Assert.AreEqual(2, MessageBox.ActiveCount); + + MessageBox.CloseAll(); + + Assert.AreEqual(0, MessageBox.ActiveCount); + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_HandlesNullTitle() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show(null, "Content"); + await UniTask.Yield(); + + var content = MessageBox.TestGetContent(); + Assert.IsNotNull(content); + Assert.AreEqual("", content.Value.title); // Null converted to empty string + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator Show_WithRealPrefab_HandlesNullContent() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Title", null); + await UniTask.Yield(); + + var content = MessageBox.TestGetContent(); + Assert.IsNotNull(content); + Assert.AreEqual("", content.Value.content); // Null converted to empty string + + MessageBox.TestSimulateButtonClick(true); + await showTask; + }); + + [UnityTest] + public IEnumerator TestSimulateButtonClick_ReturnsTrue_WhenActiveBoxExists() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + bool result = MessageBox.TestSimulateButtonClick(true); + + Assert.IsTrue(result); + await showTask; + }); + + [UnityTest] + public IEnumerator Dispose_WithRealPrefab_ClearsActiveBoxes() => UniTask.ToCoroutine(async () => + { + var showTask = MessageBox.Show("Test", "Content"); + await UniTask.Yield(); + + Assert.Greater(MessageBox.ActiveCount, 0); + + MessageBox.Dispose(); + + Assert.AreEqual(0, MessageBox.ActiveCount); + Assert.AreEqual(0, MessageBox.PooledCount); + }); + + #endregion } } diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs new file mode 100644 index 000000000..fc20fd9a9 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs @@ -0,0 +1,410 @@ +// JActionAwaiterTests.cs +// EditMode unit tests for JActionAwaiter and JActionAwaitable + +using System.Collections; +using Cysharp.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace JEngine.Util.Tests +{ + /// + /// Tests for struct via public API. + /// + [TestFixture] + public class JActionAwaitableTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + [UnityTest] + public IEnumerator ExecuteAsync_ReturnsHandle() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + Assert.IsNotNull(handle.Action); + await handle; + }); + + [UnityTest] + public IEnumerator ExecuteAsync_HandleHasCorrectAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + Assert.AreSame(action, handle.Action); + await handle; + }); + + [UnityTest] + public IEnumerator ExecuteAsync_CanBeAwaited() => UniTask.ToCoroutine(async () => + { + bool executed = false; + using var action = JAction.Create().Do(() => executed = true); + + await action.ExecuteAsync(); + + Assert.IsTrue(executed); + }); + + [UnityTest] + public IEnumerator ExecuteAsync_WithDelay_CompletesAfterDelay() => UniTask.ToCoroutine(async () => + { + bool executed = false; + using var action = JAction.Create() + .Delay(0.05f) + .Do(() => executed = true); + + var handle = action.ExecuteAsync(); + + // Initially not executed + Assert.IsFalse(executed); + + // Wait for completion + await handle; + + Assert.IsTrue(executed); + }); + } + + /// + /// Tests for struct via public API. + /// Note: ExecuteAsync always uses async path, so tests use [UnityTest] with coroutines. + /// + [TestFixture] + public class JActionAwaiterTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + #region GetAwaiter Tests + + [UnityTest] + public IEnumerator GetAwaiter_ReturnsAwaiterInstance() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + var awaiter = handle.GetAwaiter(); + + Assert.IsInstanceOf(awaiter); + await handle; + }); + + #endregion + + #region IsCompleted Tests + + [UnityTest] + public IEnumerator IsCompleted_AfterAwait_ReturnsTrue() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + // Wait for completion + await handle; + + // Get a new awaiter after completion + var awaiter = handle.GetAwaiter(); + Assert.IsTrue(awaiter.IsCompleted); + }); + + [UnityTest] + public IEnumerator IsCompleted_WithDelay_InitiallyFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(0.1f).Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + // Should not be completed immediately + Assert.IsFalse(awaiter.IsCompleted); + + // Cancel to clean up + handle.Cancel(); + await UniTask.Yield(); + }); + + #endregion + + #region GetResult Tests + + [UnityTest] + public IEnumerator GetResult_ReturnsJActionExecution() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.IsInstanceOf(result); + }); + + [UnityTest] + public IEnumerator GetResult_AfterCompletion_NotCancelled() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create() + .Delay(0.01f) + .Do(() => { }); + + var result = await action.ExecuteAsync(); + + Assert.IsFalse(result.Cancelled); + }); + + [UnityTest] + public IEnumerator GetResult_AfterCancel_IsCancelled() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create() + .Delay(10f) + .Do(() => { }); + + var handle = action.ExecuteAsync(); + handle.Cancel(); + + var result = await handle; + + Assert.IsTrue(result.Cancelled); + }); + + #endregion + + #region OnCompleted Tests + + [UnityTest] + public IEnumerator OnCompleted_AfterCompletion_InvokesContinuationImmediately() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + // Wait for completion first + await handle; + + // Now get awaiter and check OnCompleted + var awaiter = handle.GetAwaiter(); + bool invoked = false; + awaiter.OnCompleted(() => invoked = true); + + Assert.IsTrue(invoked); + }); + + [UnityTest] + public IEnumerator OnCompleted_DuringExecution_RegistersCallback() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(0.05f).Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + bool invoked = false; + awaiter.OnCompleted(() => invoked = true); + + // Not invoked immediately (still executing) + Assert.IsFalse(invoked); + + // Wait for completion by polling (don't use await handle - it overwrites OnCompleted callback) + // Use timeout to avoid hanging indefinitely if there's a regression + using var cts = new System.Threading.CancellationTokenSource(System.TimeSpan.FromSeconds(5)); + await UniTask.WaitUntil(() => invoked || !handle.Executing, cancellationToken: cts.Token); + + // Callback should have been invoked + Assert.IsTrue(invoked); + }); + + [UnityTest] + public IEnumerator OnCompleted_NullContinuation_HandlesGracefully() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + Assert.DoesNotThrow(() => awaiter.OnCompleted(null)); + await handle; + }); + + #endregion + + #region UnsafeOnCompleted Tests + + [UnityTest] + public IEnumerator UnsafeOnCompleted_AfterCompletion_InvokesContinuationImmediately() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + // Wait for completion first + await handle; + + // Now get awaiter and check UnsafeOnCompleted + var awaiter = handle.GetAwaiter(); + bool invoked = false; + awaiter.UnsafeOnCompleted(() => invoked = true); + + Assert.IsTrue(invoked); + }); + + [UnityTest] + public IEnumerator UnsafeOnCompleted_NullContinuation_HandlesGracefully() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + Assert.DoesNotThrow(() => awaiter.UnsafeOnCompleted(null)); + await handle; + }); + + #endregion + + #region UnsafeOnCompleted During Execution Tests + + [UnityTest] + public IEnumerator UnsafeOnCompleted_DuringExecution_RegistersCallback() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(0.05f).Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + bool invoked = false; + awaiter.UnsafeOnCompleted(() => invoked = true); + + // Not invoked immediately (still executing) + Assert.IsFalse(invoked); + + // Wait for completion by polling with timeout to avoid hanging indefinitely + using var cts = new System.Threading.CancellationTokenSource(System.TimeSpan.FromSeconds(5)); + await UniTask.WaitUntil(() => invoked || !handle.Executing, cancellationToken: cts.Token); + + // Callback should have been invoked + Assert.IsTrue(invoked); + }); + + #endregion + } + + /// + /// Tests for nested JAction execution patterns. + /// + [TestFixture] + public class JActionNestedExecutionTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + #region Sequential Nested Execution Tests + + [UnityTest] + public IEnumerator NestedExecution_ExecutesInSequence() => UniTask.ToCoroutine(async () => + { + int executionOrder = 0; + int first = 0, second = 0, third = 0; + + using var action = JAction.Create() + .Do(() => first = ++executionOrder) + .Do(() => second = ++executionOrder) + .Do(() => third = ++executionOrder); + + await action.ExecuteAsync(); + + Assert.AreEqual(1, first); + Assert.AreEqual(2, second); + Assert.AreEqual(3, third); + }); + + [UnityTest] + public IEnumerator NestedExecution_WithDelays_WaitsForEach() => UniTask.ToCoroutine(async () => + { + bool step1 = false, step2 = false, step3 = false; + + using var action = JAction.Create() + .Do(() => step1 = true) + .Delay(0.02f) + .Do(() => step2 = true) + .Delay(0.02f) + .Do(() => step3 = true); + + await action.ExecuteAsync(); + + Assert.IsTrue(step1); + Assert.IsTrue(step2); + Assert.IsTrue(step3); + }); + + #endregion + + #region Parallel Execution Tests + + [UnityTest] + public IEnumerator ParallelExecution_RunsMultipleHandles() => UniTask.ToCoroutine(async () => + { + int count = 0; + + using var action = JAction.Create() + .Parallel() + .Delay(0.02f) + .Do(() => System.Threading.Interlocked.Increment(ref count)); + + var handle1 = action.ExecuteAsync(); + var handle2 = action.ExecuteAsync(); + var handle3 = action.ExecuteAsync(); + + await UniTask.WhenAll(handle1.AsUniTask(), handle2.AsUniTask(), handle3.AsUniTask()); + + Assert.AreEqual(3, count); + }); + + #endregion + + #region Cancellation Tests + + [UnityTest] + public IEnumerator Cancel_DuringNestedExecution_StopsExecution() => UniTask.ToCoroutine(async () => + { + bool step1 = false; + bool step2 = false; + + using var action = JAction.Create() + .Do(() => step1 = true) + .Delay(10f) + .Do(() => step2 = true); + + var handle = action.ExecuteAsync(); + + // Wait for first step with timeout to avoid hanging indefinitely + using var cts = new System.Threading.CancellationTokenSource(System.TimeSpan.FromSeconds(5)); + await UniTask.WaitUntil(() => step1, cancellationToken: cts.Token); + + handle.Cancel(); + await handle; + + Assert.IsTrue(step1); + Assert.IsFalse(step2); + }); + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs.meta new file mode 100644 index 000000000..7e94763d8 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionAwaiterTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a48bd6068c4d84fba8e3a4226732dd9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs new file mode 100644 index 000000000..3c2a7cb78 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs @@ -0,0 +1,550 @@ +// JActionExecutionHandleTests.cs +// EditMode unit tests for JActionExecutionHandle and JActionExecutionAwaiter + +using System.Collections; +using Cysharp.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace JEngine.Util.Tests +{ + /// + /// Tests for struct. + /// Note: ExecuteAsync always uses async path, so completion tests use [UnityTest]. + /// + [TestFixture] + public class JActionExecutionHandleTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + #region Action Property Tests + + [UnityTest] + public IEnumerator Action_ReturnsAssociatedJAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + Assert.AreSame(action, handle.Action); + await handle; + }); + + [UnityTest] + public IEnumerator Action_MultipleHandles_ReturnSameAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Parallel().Do(() => { }); + var handle1 = action.ExecuteAsync(); + var handle2 = action.ExecuteAsync(); + + Assert.AreSame(action, handle1.Action); + Assert.AreSame(action, handle2.Action); + + await UniTask.WhenAll(handle1.AsUniTask(), handle2.AsUniTask()); + }); + + #endregion + + #region Cancelled Property Tests + + [Test] + public void Cancelled_DefaultHandle_ReturnsFalse() + { + var handle = default(JActionExecutionHandle); + + Assert.IsFalse(handle.Cancelled); + } + + [UnityTest] + public IEnumerator Cancelled_AfterCompletion_ReturnsFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + Assert.IsFalse(handle.Cancelled); + }); + + [UnityTest] + public IEnumerator Cancelled_AfterCancel_ReturnsTrue() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f); + var handle = action.ExecuteAsync(); + + handle.Cancel(); + + Assert.IsTrue(handle.Cancelled); + await UniTask.Yield(); + }); + + #endregion + + #region Executing Property Tests + + [Test] + public void Executing_DefaultHandle_ReturnsFalse() + { + var handle = default(JActionExecutionHandle); + + Assert.IsFalse(handle.Executing); + } + + [UnityTest] + public IEnumerator Executing_AfterCompletion_ReturnsFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + Assert.IsFalse(handle.Executing); + }); + + [UnityTest] + public IEnumerator Executing_DuringExecution_ReturnsTrue() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f); + var handle = action.ExecuteAsync(); + + Assert.IsTrue(handle.Executing); + + handle.Cancel(); + await UniTask.Yield(); + }); + + [UnityTest] + public IEnumerator Executing_AfterCancel_ReturnsFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f); + var handle = action.ExecuteAsync(); + + handle.Cancel(); + await handle; + + Assert.IsFalse(handle.Executing); + }); + + #endregion + + #region Cancel Tests + + [Test] + public void Cancel_DefaultHandle_DoesNotThrow() + { + var handle = default(JActionExecutionHandle); + + Assert.DoesNotThrow(() => handle.Cancel()); + } + + [UnityTest] + public IEnumerator Cancel_CompletedHandle_DoesNotThrow() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + Assert.DoesNotThrow(() => handle.Cancel()); + }); + + [UnityTest] + public IEnumerator Cancel_MultipleTimes_DoesNotThrow() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f); + var handle = action.ExecuteAsync(); + + Assert.DoesNotThrow(() => + { + handle.Cancel(); + handle.Cancel(); + handle.Cancel(); + }); + + await handle; + }); + + [UnityTest] + public IEnumerator Cancel_StopsExecution() => UniTask.ToCoroutine(async () => + { + bool completed = false; + using var action = JAction.Create() + .Delay(10f) + .Do(() => completed = true); + + var handle = action.ExecuteAsync(); + handle.Cancel(); + + Assert.IsTrue(handle.Cancelled); + Assert.IsFalse(completed); + await UniTask.Yield(); + }); + + [UnityTest] + public IEnumerator Cancel_InvokesOnCancelCallback() => UniTask.ToCoroutine(async () => + { + bool cancelled = false; + using var action = JAction.Create() + .Delay(10f) + .OnCancel(() => cancelled = true); + + var handle = action.ExecuteAsync(); + handle.Cancel(); + + Assert.IsTrue(cancelled); + await UniTask.Yield(); + }); + + #endregion + + #region GetAwaiter Tests + + [UnityTest] + public IEnumerator GetAwaiter_ReturnsAwaiter() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + var awaiter = handle.GetAwaiter(); + + Assert.IsInstanceOf(awaiter); + await handle; + }); + + [UnityTest] + public IEnumerator GetAwaiter_AfterCompletion_ReturnsCompletedAwaiter() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + var awaiter = handle.GetAwaiter(); + Assert.IsTrue(awaiter.IsCompleted); + }); + + #endregion + + #region Dispose Tests + + [UnityTest] + public IEnumerator Dispose_ReturnsActionToPool() => UniTask.ToCoroutine(async () => + { + int initialCount = JAction.PooledCount; + // Use using to ensure action is disposed even if ExecuteAsync throws + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + handle.Dispose(); + + // Note: action.Dispose() is called twice (by handle.Dispose and using), + // but JAction.Dispose is idempotent so this is safe + Assert.AreEqual(initialCount + 1, JAction.PooledCount); + }); + + [Test] + public void Dispose_DefaultHandle_DoesNotThrow() + { + var handle = default(JActionExecutionHandle); + + Assert.DoesNotThrow(() => handle.Dispose()); + } + + [UnityTest] + public IEnumerator Dispose_MultipleTimes_DoesNotThrow() => UniTask.ToCoroutine(async () => + { + // Use using to ensure action is disposed even if ExecuteAsync throws + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + Assert.DoesNotThrow(() => + { + handle.Dispose(); + handle.Dispose(); + }); + }); + + #endregion + + #region Implicit Operator Tests + + [UnityTest] + public IEnumerator ImplicitOperator_ConvertsToJAction() => UniTask.ToCoroutine(async () => + { + // Use using to ensure action is disposed even if ExecuteAsync throws + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + JAction converted = handle; + + Assert.AreSame(action, converted); + + await handle; + }); + + [Test] + public void ImplicitOperator_DefaultHandle_ReturnsNull() + { + var handle = default(JActionExecutionHandle); + + JAction converted = handle; + + Assert.IsNull(converted); + } + + #endregion + + #region AsUniTask Tests + + [UnityTest] + public IEnumerator AsUniTask_ReturnsUniTask() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + var result = await handle.AsUniTask(); + + Assert.IsInstanceOf(result); + }); + + [UnityTest] + public IEnumerator AsUniTask_WithDelay_CompletesAfterDelay() => UniTask.ToCoroutine(async () => + { + bool executed = false; + using var action = JAction.Create() + .Delay(0.05f) + .Do(() => executed = true); + + var handle = action.ExecuteAsync(); + await handle.AsUniTask(); + + Assert.IsTrue(executed); + }); + + #endregion + } + + /// + /// Tests for struct. + /// + [TestFixture] + public class JActionExecutionAwaiterTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + #region IsCompleted Tests + + [UnityTest] + public IEnumerator IsCompleted_AfterCompletion_ReturnsTrue() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + var awaiter = handle.GetAwaiter(); + Assert.IsTrue(awaiter.IsCompleted); + }); + + [UnityTest] + public IEnumerator IsCompleted_WithDelay_InitiallyFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f).Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + Assert.IsFalse(awaiter.IsCompleted); + + handle.Cancel(); + await UniTask.Yield(); + }); + + #endregion + + #region GetResult Tests + + [UnityTest] + public IEnumerator GetResult_ReturnsJActionExecution() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.IsInstanceOf(result); + }); + + [UnityTest] + public IEnumerator GetResult_AfterCompletion_NotCancelled() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.IsFalse(result.Cancelled); + }); + + [UnityTest] + public IEnumerator GetResult_ReturnsAssociatedAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.AreSame(action, result.Action); + }); + + [UnityTest] + public IEnumerator GetResult_CancelledExecution_IsCancelled() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f).Do(() => { }); + var handle = action.ExecuteAsync(); + + handle.Cancel(); + + var result = await handle; + + Assert.IsTrue(result.Cancelled); + }); + + #endregion + + #region OnCompleted Tests + + [UnityTest] + public IEnumerator OnCompleted_AfterCompletion_InvokesContinuationImmediately() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + var awaiter = handle.GetAwaiter(); + bool invoked = false; + awaiter.OnCompleted(() => invoked = true); + + Assert.IsTrue(invoked); + }); + + [UnityTest] + public IEnumerator OnCompleted_NullContinuation_HandlesGracefully() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + Assert.DoesNotThrow(() => awaiter.OnCompleted(null)); + await handle; + }); + + #endregion + + #region UnsafeOnCompleted Tests + + [UnityTest] + public IEnumerator UnsafeOnCompleted_AfterCompletion_InvokesContinuationImmediately() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + + await handle; + + var awaiter = handle.GetAwaiter(); + bool invoked = false; + awaiter.UnsafeOnCompleted(() => invoked = true); + + Assert.IsTrue(invoked); + }); + + [UnityTest] + public IEnumerator UnsafeOnCompleted_NullContinuation_HandlesGracefully() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var handle = action.ExecuteAsync(); + var awaiter = handle.GetAwaiter(); + + Assert.DoesNotThrow(() => awaiter.UnsafeOnCompleted(null)); + await handle; + }); + + #endregion + } + + /// + /// Tests for struct. + /// + [TestFixture] + public class JActionExecutionTests + { + [SetUp] + public void SetUp() + { + JAction.ClearPool(); + } + + [TearDown] + public void TearDown() + { + JAction.ClearPool(); + } + + [UnityTest] + public IEnumerator Action_ReturnsAssociatedJAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.AreSame(action, result.Action); + }); + + [UnityTest] + public IEnumerator Cancelled_AfterCompletion_ReturnsFalse() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + Assert.IsFalse(result.Cancelled); + }); + + [UnityTest] + public IEnumerator Cancelled_AfterCancel_ReturnsTrue() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Delay(10f).Do(() => { }); + var handle = action.ExecuteAsync(); + handle.Cancel(); + + var result = await handle; + + Assert.IsTrue(result.Cancelled); + }); + + [UnityTest] + public IEnumerator ImplicitOperator_ConvertsToJAction() => UniTask.ToCoroutine(async () => + { + using var action = JAction.Create().Do(() => { }); + var result = await action.ExecuteAsync(); + + JAction converted = result; + + Assert.AreSame(action, converted); + }); + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs.meta new file mode 100644 index 000000000..51fd5ea0e --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionExecutionHandleTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95bf91b62c5854c22b6b37d0a8bdb2bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: