diff --git a/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs b/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs index 82cdc2a17..f79051f62 100644 --- a/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs +++ b/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs @@ -25,6 +25,7 @@ public sealed class OnionAssemblyDependencyTests private const string FirstPartyToolsAssemblyName = "UnityCLILoop.FirstPartyTools.Editor"; private const string FirstPartyToolsAssemblyNamePrefix = "UnityCLILoop.FirstPartyTools."; private const string ClearConsoleAssemblyName = "UnityCLILoop.FirstPartyTools.ClearConsole.Editor"; + private const string CommonConsoleAssemblyName = "UnityCLILoop.FirstPartyTools.Common.Console.Editor"; private const string CompileAssemblyName = "UnityCLILoop.FirstPartyTools.Compile.Editor"; private const string ControlPlayModeAssemblyName = "UnityCLILoop.FirstPartyTools.ControlPlayMode.Editor"; private const string ExecuteDynamicCodeAssemblyName = "UnityCLILoop.FirstPartyTools.ExecuteDynamicCode.Editor"; @@ -507,6 +508,7 @@ public void InfrastructureAsmdef_WhenLoaded_DependsOnApplicationRuntimeAndDoesNo InternalApiBridgeAssemblyName, ApplicationAssemblyName, DomainAssemblyName, + CommonConsoleAssemblyName, PausePointsRuntimeAssemblyName, ToolContractsAssemblyName })); @@ -881,6 +883,11 @@ public void DomainReloadStateRegistration_WhenLoaded_DoesNotReadSettingsSynchron public void SetupWizardStartup_WhenLoaded_SchedulesVersionCheckInsteadOfReadingSettingsSynchronously() { // Tests that Setup Wizard settings reads run after the synchronous Editor startup hook. + // + // A cold-start session that hits Unity's native "Scripts have compiler errors" dialog + // never flushes EditorApplication.delayCall again for the rest of that process's + // lifetime, so this startup check rides on a self-unsubscribing EditorApplication.update + // tick instead of delayCall. string setupWizardSource = ReadProductionSource( "Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs"); string setupWizardStartupFlowSource = ReadProductionSource( @@ -888,7 +895,7 @@ public void SetupWizardStartup_WhenLoaded_SchedulesVersionCheckInsteadOfReadingS Assert.That( setupWizardSource, - Does.Contain("EditorApplication.delayCall += startupFlow.TryShowOnVersionChange;")); + Does.Contain("EditorApplication.update += RunStartupCheckOnFirstUpdateTick;")); Assert.That( setupWizardStartupFlowSource, Does.Contain("EditorApplication.delayCall += () => _showWindowOnVersionChange();")); @@ -896,15 +903,16 @@ public void SetupWizardStartup_WhenLoaded_SchedulesVersionCheckInsteadOfReadingS } [Test] - public void SetupWizardStartup_WhenMigrationAutoScanIsRequested_SchedulesAutoScanThroughDelayCall() + public void SetupWizardStartup_WhenMigrationAutoScanIsRequested_SchedulesAutoScanThroughEditorUpdatePolling() { - // Tests that startup migration auto-scan runs through a delayed Editor callback. + // Tests that startup migration auto-scan polls via EditorApplication.update instead of + // delayCall, since delayCall stops flushing after the native compiler-errors dialog. string setupWizardStartupFlowSource = ReadProductionSource( "Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs"); Assert.That( setupWizardStartupFlowSource, - Does.Contain("EditorApplication.delayCall += () => _showThirdPartyMigrationAutoScan();")); + Does.Contain("EditorApplication.update += PollThirdPartyToolMigrationAutoScan;")); } [Test] diff --git a/Assets/Tests/Editor/SetupWizardWindowTests.cs b/Assets/Tests/Editor/SetupWizardWindowTests.cs index 9c1d81923..18d4ed31c 100644 --- a/Assets/Tests/Editor/SetupWizardWindowTests.cs +++ b/Assets/Tests/Editor/SetupWizardWindowTests.cs @@ -26,7 +26,6 @@ public class SetupWizardWindowTests private string _settingsFileContent; private IUnityCliLoopEditorSettingsPort _editorSettingsPort; private UnityCliLoopEditorSettingsRepository _editorSettingsRepository; - private UnityCliLoopSessionFlagsRepository _sessionFlagsRepository; private UnityCliLoopEditorSessionStateSnapshot _originalSessionState; [SetUp] @@ -43,7 +42,6 @@ public void SetUp() DeleteIfExists(SettingsFilePath); _editorSettingsPort = UnityCliLoopEditorSettingsTestFactory.CreatePortWithRepository(out _editorSettingsRepository); - _sessionFlagsRepository = UnityCliLoopEditorSessionStateTestFactory.CreateSessionFlagsRepository(); _originalSessionState = UnityCliLoopEditorSessionStateTestFactory.CaptureSnapshot(); UnityCliLoopEditorSessionStateTestFactory.ClearAll(); SetupWizardWindow.InitializeEditorServices( @@ -183,22 +181,29 @@ public void ShouldAutoScanThirdPartyToolMigration_ReturnsExpectedValue( Assert.That(shouldAutoScan, Is.EqualTo(expected)); } - [Test] - public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenEnabled_SetsSessionFlag() - { - // Verifies that the V2-to-V3 upgrade signal is stored only in the current Editor session. - SetupWizardStartupFlow.MaybeMarkThirdPartyToolMigrationAutoScan(_sessionFlagsRepository, true); - - Assert.That(_sessionFlagsRepository.GetShouldAutoScanThirdPartyToolMigration(), Is.True); - } - - [Test] - public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenDisabled_KeepsSessionFlagFalse() - { - // Verifies that non-upgrade version checks do not request migration scans. - SetupWizardStartupFlow.MaybeMarkThirdPartyToolMigrationAutoScan(_sessionFlagsRepository, false); - - Assert.That(_sessionFlagsRepository.GetShouldAutoScanThirdPartyToolMigration(), Is.False); + [TestCase(true, false, 0d, 10d, MigrationAutoScanPollAction.ContinueWaiting)] + [TestCase(true, true, 0d, 10d, MigrationAutoScanPollAction.ContinueWaiting)] + [TestCase(false, false, 0d, 10d, MigrationAutoScanPollAction.Terminate)] + [TestCase(false, true, 0d, 10d, MigrationAutoScanPollAction.RunDetection)] + [TestCase(false, true, 5d, 10d, MigrationAutoScanPollAction.RunDetection)] + [TestCase(false, true, 10d, 10d, MigrationAutoScanPollAction.FallBackToFullScan)] + [TestCase(false, true, 15d, 10d, MigrationAutoScanPollAction.FallBackToFullScan)] + public void DecideMigrationAutoScanPollAction_ReturnsExpectedAction( + bool isCompiling, + bool scriptCompilationFailed, + double elapsedSeconds, + double timeoutSeconds, + MigrationAutoScanPollAction expected) + { + // Verifies the pure poll decision function used to replace the unreliable + // delayCall-based migration auto-scan trigger with an EditorApplication.update poll. + MigrationAutoScanPollAction action = SetupWizardStartupFlow.DecideMigrationAutoScanPollAction( + isCompiling, + scriptCompilationFailed, + elapsedSeconds, + timeoutSeconds); + + Assert.That(action, Is.EqualTo(expected)); } [Test] diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs b/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs new file mode 100644 index 000000000..9523df623 --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; + +using NUnit.Framework; + +using io.github.hatayama.UnityCliLoop.Infrastructure; + +namespace io.github.hatayama.UnityCliLoop.Tests.Editor +{ + /// + /// Test fixture that verifies compile-error-log entries are matched against V2 legacy API tokens + /// and reduced to a deduplicated set of migration target file paths. + /// + public sealed class ThirdPartyToolMigrationCompileErrorLogMatcherTests + { + [Test] + public void Match_WhenNoEntryContainsLegacyToken_ReturnsEmptyResult() + { + // Verifies that unrelated V3 compile errors produce no matched entries and no target file paths. + List entries = new List + { + new CompileErrorLogEntry( + "Assets/Editor/MyTool.cs(1,1): error CS0103: The name 'undefinedSymbol' does not exist in the current context", + "Assets/Editor/MyTool.cs", + 1) + }; + + ThirdPartyToolMigrationCompileErrorLogMatchResult result = + ThirdPartyToolMigrationCompileErrorLogMatcher.Match(entries); + + Assert.That(result.MatchedEntries, Is.Empty); + Assert.That(result.TargetFilePaths, Is.Empty); + } + + [Test] + public void Match_WhenEntryContainsLegacyToken_ReturnsMatchedEntryAndTargetFilePath() + { + // Verifies that an entry whose message contains a legacy API token is included in both + // the matched-entries list and the target file path list. + List entries = new List + { + new CompileErrorLogEntry( + "Assets/Editor/MyTool.cs(3,25): error CS0234: The type or namespace name 'uLoopMCP' " + + "does not exist in the namespace 'io.github.hatayama' (are you missing an assembly reference?)", + "Assets/Editor/MyTool.cs", + 3) + }; + + ThirdPartyToolMigrationCompileErrorLogMatchResult result = + ThirdPartyToolMigrationCompileErrorLogMatcher.Match(entries); + + Assert.That(result.MatchedEntries.Count, Is.EqualTo(1)); + Assert.That(result.TargetFilePaths, Is.EqualTo(new[] { "Assets/Editor/MyTool.cs" })); + } + + [Test] + public void Match_WhenMultipleEntriesShareTheSameFilePath_DeduplicatesTargetFilePaths() + { + // Verifies that multiple legacy-token-matching errors in the same file collapse to one target path. + List entries = new List + { + new CompileErrorLogEntry( + "Assets/Editor/MyTool.cs(3,25): error CS0234: The type or namespace name 'uLoopMCP' " + + "does not exist in the namespace 'io.github.hatayama' (are you missing an assembly reference?)", + "Assets/Editor/MyTool.cs", + 3), + new CompileErrorLogEntry( + "Assets/Editor/MyTool.cs(9,14): error CS0246: The type or namespace name 'AbstractUnityTool' " + + "could not be found (are you missing a using directive or an assembly reference?)", + "Assets/Editor/MyTool.cs", + 9) + }; + + ThirdPartyToolMigrationCompileErrorLogMatchResult result = + ThirdPartyToolMigrationCompileErrorLogMatcher.Match(entries); + + Assert.That(result.MatchedEntries.Count, Is.EqualTo(2)); + Assert.That(result.TargetFilePaths, Is.EqualTo(new[] { "Assets/Editor/MyTool.cs" })); + } + + [Test] + public void Match_WhenEntriesMixMatchingAndNonMatching_OnlyIncludesMatchingFilePaths() + { + // Verifies that a non-matching entry does not contribute its file path even when it is + // interleaved with matching entries from other files. + List entries = new List + { + new CompileErrorLogEntry( + "Assets/Editor/Unrelated.cs(1,1): error CS0103: The name 'undefinedSymbol' does not exist in the current context", + "Assets/Editor/Unrelated.cs", + 1), + new CompileErrorLogEntry( + "Assets/Editor/LegacyTool.cs(2,6): error CS0246: The type or namespace name 'McpTool' " + + "could not be found (are you missing a using directive or an assembly reference?)", + "Assets/Editor/LegacyTool.cs", + 2) + }; + + ThirdPartyToolMigrationCompileErrorLogMatchResult result = + ThirdPartyToolMigrationCompileErrorLogMatcher.Match(entries); + + Assert.That(result.MatchedEntries.Count, Is.EqualTo(1)); + Assert.That(result.TargetFilePaths, Is.EqualTo(new[] { "Assets/Editor/LegacyTool.cs" })); + } + + [Test] + public void Match_WhenEntriesIsNull_Throws() + { + // Verifies fail-fast behavior when the entry collection itself is missing. + Assert.Throws(() => + ThirdPartyToolMigrationCompileErrorLogMatcher.Match(null)); + } + } +} diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs.meta b/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs.meta new file mode 100644 index 000000000..42851f407 --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationCompileErrorLogMatcherTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48981f198be2842188e338ec04026f34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs b/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs new file mode 100644 index 000000000..9d2e65b0f --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs @@ -0,0 +1,144 @@ +using System.Collections.Generic; + +using NUnit.Framework; + +using io.github.hatayama.UnityCliLoop.Infrastructure; + +namespace io.github.hatayama.UnityCliLoop.Tests.Editor +{ + /// + /// Verifies that raw Unity Console error text is parsed back into structured + /// CompileErrorLogEntry values, including Windows-style paths (backslashes, drive letters, + /// spaces) that must parse correctly regardless of the host OS running the test. + /// + public sealed class ThirdPartyToolMigrationConsoleErrorParserTests + { + private const string ProjectRoot = "/Users/dev/Project"; + + [Test] + public void Parse_WithProjectRelativeUnixPath_ReturnsEntryWithAbsolutePath() + { + // Verifies a standard csc/Roslyn diagnostic line with a project-relative Unix-style path + // is parsed into an absolute file path, line number, and code-prefixed message. + List rawMessages = new List + { + "Assets/Editor/Foo.cs(3,25): error CS0246: The type or namespace name 'Bar' could not be found" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(1)); + Assert.That(entries[0].FilePath, Is.EqualTo("/Users/dev/Project/Assets/Editor/Foo.cs")); + Assert.That(entries[0].LineNumber, Is.EqualTo(3)); + Assert.That(entries[0].Message, Does.Contain("Bar")); + } + + [Test] + public void Parse_WithBackslashSeparatedRelativePath_NormalizesToForwardSlashAbsolutePath() + { + // Verifies Windows-style backslash separators in a project-relative path are normalized + // to forward slashes and combined with the project root, without relying on the host OS's + // own path-separator handling. + List rawMessages = new List + { + @"Assets\Editor\Foo.cs(3,25): error CS0246: The type or namespace name 'Bar' could not be found" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(1)); + Assert.That(entries[0].FilePath, Is.EqualTo("/Users/dev/Project/Assets/Editor/Foo.cs")); + } + + [Test] + public void Parse_WithWindowsDriveLetterAbsolutePath_KeepsPathAbsoluteWithoutProjectRoot() + { + // Verifies a Windows drive-letter absolute path is recognized as already-rooted (via an + // explicit drive-letter check, not Path.IsPathRooted, which is host-OS dependent) and is + // not incorrectly combined with the project root. + List rawMessages = new List + { + @"C:\Users\dev\Project\Assets\Editor\Foo.cs(10,1): error CS0246: The type or namespace name 'Bar' could not be found" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(1)); + Assert.That(entries[0].FilePath, Is.EqualTo("C:/Users/dev/Project/Assets/Editor/Foo.cs")); + } + + [Test] + public void Parse_WithSpacesInPath_ParsesFullPathIncludingSpaces() + { + // Verifies a path containing spaces (e.g. a "My Tools" folder) is parsed in full, not + // truncated at the space. + List rawMessages = new List + { + "Assets/My Tools/Foo.cs(5,10): error CS0246: The type or namespace name 'Bar' could not be found" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(1)); + Assert.That(entries[0].FilePath, Is.EqualTo("/Users/dev/Project/Assets/My Tools/Foo.cs")); + } + + [Test] + public void Parse_WithWarningSeverity_IsSkipped() + { + // Verifies warning-severity diagnostic lines are not treated as compile errors. + List rawMessages = new List + { + "Assets/Editor/Foo.cs(3,25): warning CS0219: The variable 'x' is never used" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(0)); + } + + [Test] + public void Parse_WithNonDiagnosticFormatLine_IsSkippedWithoutThrowing() + { + // Verifies plain (non-compiler-diagnostic) console messages are silently ignored. + List rawMessages = new List + { + "This is a regular Debug.LogError message with no file/line prefix" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(0)); + } + + [Test] + public void Parse_WithMultiLineMessage_UsesOnlyFirstLine() + { + // Verifies only the first physical line of a multi-line console message is parsed for the + // diagnostic file/line prefix. + List rawMessages = new List + { + "Assets/Editor/Foo.cs(3,25): error CS0246: The type or namespace name 'Bar' could not be found\nSome trailing detail line" + }; + + List entries = ThirdPartyToolMigrationConsoleErrorParser.Parse( + rawMessages, + ProjectRoot); + + Assert.That(entries.Count, Is.EqualTo(1)); + Assert.That(entries[0].FilePath, Is.EqualTo("/Users/dev/Project/Assets/Editor/Foo.cs")); + } + } +} diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs.meta b/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs.meta new file mode 100644 index 000000000..588c2cae7 --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationConsoleErrorParserTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4545e0f72b321458895a76907a75784f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs b/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs new file mode 100644 index 000000000..e7b83045b --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs @@ -0,0 +1,83 @@ +using NUnit.Framework; + +using io.github.hatayama.UnityCliLoop.Infrastructure; + +namespace io.github.hatayama.UnityCliLoop.Tests.Editor +{ + /// + /// Test fixture that verifies compile-error-message token matching for V2 legacy API detection. + /// + public sealed class ThirdPartyToolMigrationDetectionRulesTests + { + [Test] + public void ContainsLegacyApiToken_WhenMessageContainsLegacyNamespaceSegment_ReturnsTrue() + { + // Verifies that a CS0234 message shaped like Roslyn's actual segment-only report is detected. + const string message = + "Assets/Editor/MyTool.cs(3,25): error CS0234: The type or namespace name 'uLoopMCP' " + + "does not exist in the namespace 'io.github.hatayama' (are you missing an assembly reference?)"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.True); + } + + [Test] + public void ContainsLegacyApiToken_WhenMessageContainsLegacyAssemblyName_ReturnsTrue() + { + // Verifies that asmdef-reference-shaped errors referencing the legacy assembly name are detected. + const string message = "error: Assembly 'uLoopMCP.Editor' could not be resolved."; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.True); + } + + [Test] + public void ContainsLegacyApiToken_WhenMessageContainsRenamedLegacyTypeName_ReturnsTrue() + { + // Verifies that CS0246-shaped errors for a renamed legacy base type are detected without depending on the error code. + const string message = "Assets/Editor/MyTool.cs(5,14): error CS0246: The type or namespace name " + + "'AbstractUnityTool' could not be found (are you missing a using directive or an assembly reference?)"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.True); + } + + [Test] + public void ContainsLegacyApiToken_WhenMessageContainsAttributeSuffixStrippedForm_ReturnsTrue() + { + // Verifies that Roslyn's attribute-usage error, which reports 'McpTool' without the 'Attribute' suffix, is still detected. + const string message = "Assets/Editor/MyTool.cs(2,6): error CS0246: The type or namespace name " + + "'McpTool' could not be found (are you missing a using directive or an assembly reference?)"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.True); + } + + [Test] + public void ContainsLegacyApiToken_WhenTokenIsSubstringOfUnrelatedIdentifier_ReturnsFalse() + { + // Verifies identifier-boundary matching: 'IUnityTool' must not match inside 'IUnityToolbarButton'. + const string message = "Assets/Editor/MyTool.cs(9,10): error CS0246: The type or namespace name " + + "'IUnityToolbarButton' could not be found (are you missing a using directive or an assembly reference?)"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.False); + } + + [Test] + public void ContainsLegacyApiToken_WhenMessageIsUnrelatedV3CompileError_ReturnsFalse() + { + // Verifies that ordinary V3 compile errors unrelated to legacy migration do not match. + const string message = "Assets/Editor/MyTool.cs(1,1): error CS0103: The name 'undefinedSymbol' " + + "does not exist in the current context"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.False); + } + + [Test] + public void ContainsLegacyApiToken_WhenMessageReferencesTypeSharedByLegacyAndCurrentNames_ReturnsFalse() + { + // Verifies that names unchanged between V2 and V3 (e.g. ServiceResult) are excluded from the token set, + // since matching them would false-positive on unrelated V3-only compile errors. + const string message = "Assets/Editor/MyTool.cs(4,9): error CS0246: The type or namespace name " + + "'ServiceResult' could not be found (are you missing a using directive or an assembly reference?)"; + + Assert.That(ThirdPartyToolMigrationDetectionRules.ContainsLegacyApiToken(message), Is.False); + } + } +} diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs.meta b/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs.meta new file mode 100644 index 000000000..74100b241 --- /dev/null +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationDetectionRulesTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1237101791612415e9fed477a7e29353 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor/ThirdPartyToolMigrationWizardWindowTests.cs b/Assets/Tests/Editor/ThirdPartyToolMigrationWizardWindowTests.cs index ccbb7ebdf..18d070018 100644 --- a/Assets/Tests/Editor/ThirdPartyToolMigrationWizardWindowTests.cs +++ b/Assets/Tests/Editor/ThirdPartyToolMigrationWizardWindowTests.cs @@ -322,6 +322,54 @@ public void ShowNoMigrationTargetsState_DisablesCheckButtonWithoutShowingCloseBu Assert.That(closeButton.style.display.value, Is.EqualTo(DisplayStyle.None)); } + [Test] + public void ShowMigrationCompleteState_ShowsDistinctWordingFromNoMigrationTargetsState() + { + // Verifies that the just-migrated state reads as complete rather than as a generic idle "nothing to migrate", which is ambiguous with the background compile Migrate just triggered. + VisualElement root = new(); + ThirdPartyToolMigrationWizardView view = ThirdPartyToolMigrationWizardView.Create( + root, + () => { }, + () => { }, + _ => { }, + () => { }, + () => { }); + + view.ShowMigrationCompleteState(isMigrating: false); + + TextField statusTextField = root.Query(className: "setup-step__status-label--standalone").First(); + Button checkButton = root.Query